mmc: mtk-sd: Use readl_poll_timeout instead of open-coded polling
authorAngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Thu, 16 Dec 2021 12:57:44 +0000 (13:57 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Jan 2022 10:04:50 +0000 (11:04 +0100)
[ Upstream commit ffaea6ebfe9ce06ebb3a54811a47688f2b0893cd ]

Replace all instances of open-coded while loops for polling registers
with calls to readl_poll_timeout() and, while at it, also fix some
possible infinite loop instances.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Link: https://lore.kernel.org/r/20211216125748.179602-1-angelogioacchino.delregno@collabora.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/mmc/host/mtk-sd.c

index 9e6dab7..1ac9201 100644 (file)
@@ -628,12 +628,11 @@ static void msdc_reset_hw(struct msdc_host *host)
        u32 val;
 
        sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_RST);
-       while (readl(host->base + MSDC_CFG) & MSDC_CFG_RST)
-               cpu_relax();
+       readl_poll_timeout(host->base + MSDC_CFG, val, !(val & MSDC_CFG_RST), 0, 0);
 
        sdr_set_bits(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
-       while (readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_CLR)
-               cpu_relax();
+       readl_poll_timeout(host->base + MSDC_FIFOCS, val,
+                          !(val & MSDC_FIFOCS_CLR), 0, 0);
 
        val = readl(host->base + MSDC_INT);
        writel(val, host->base + MSDC_INT);
@@ -806,8 +805,9 @@ static void msdc_gate_clock(struct msdc_host *host)
        clk_disable_unprepare(host->h_clk);
 }
 
-static void msdc_ungate_clock(struct msdc_host *host)
+static int msdc_ungate_clock(struct msdc_host *host)
 {
+       u32 val;
        int ret;
 
        clk_prepare_enable(host->h_clk);
@@ -817,11 +817,11 @@ static void msdc_ungate_clock(struct msdc_host *host)
        ret = clk_bulk_prepare_enable(MSDC_NR_CLOCKS, host->bulk_clks);
        if (ret) {
                dev_err(host->dev, "Cannot enable pclk/axi/ahb clock gates\n");
-               return;
+               return ret;
        }
 
-       while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
-               cpu_relax();
+       return readl_poll_timeout(host->base + MSDC_CFG, val,
+                                 (val & MSDC_CFG_CKSTB), 1, 20000);
 }
 
 static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
@@ -832,6 +832,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
        u32 div;
        u32 sclk;
        u32 tune_reg = host->dev_comp->pad_tune_reg;
+       u32 val;
 
        if (!hz) {
                dev_dbg(host->dev, "set mclk to 0\n");
@@ -912,8 +913,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
        else
                clk_prepare_enable(clk_get_parent(host->src_clk));
 
-       while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
-               cpu_relax();
+       readl_poll_timeout(host->base + MSDC_CFG, val, (val & MSDC_CFG_CKSTB), 0, 0);
        sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
        mmc->actual_clock = sclk;
        host->mclk = hz;
@@ -1223,13 +1223,13 @@ static bool msdc_cmd_done(struct msdc_host *host, int events,
 static inline bool msdc_cmd_is_ready(struct msdc_host *host,
                struct mmc_request *mrq, struct mmc_command *cmd)
 {
-       /* The max busy time we can endure is 20ms */
-       unsigned long tmo = jiffies + msecs_to_jiffies(20);
+       u32 val;
+       int ret;
 
-       while ((readl(host->base + SDC_STS) & SDC_STS_CMDBUSY) &&
-                       time_before(jiffies, tmo))
-               cpu_relax();
-       if (readl(host->base + SDC_STS) & SDC_STS_CMDBUSY) {
+       /* The max busy time we can endure is 20ms */
+       ret = readl_poll_timeout_atomic(host->base + SDC_STS, val,
+                                       !(val & SDC_STS_CMDBUSY), 1, 20000);
+       if (ret) {
                dev_err(host->dev, "CMD bus busy detected\n");
                host->error |= REQ_CMD_BUSY;
                msdc_cmd_done(host, MSDC_INT_CMDTMO, mrq, cmd);
@@ -1237,12 +1237,10 @@ static inline bool msdc_cmd_is_ready(struct msdc_host *host,
        }
 
        if (mmc_resp_type(cmd) == MMC_RSP_R1B || cmd->data) {
-               tmo = jiffies + msecs_to_jiffies(20);
                /* R1B or with data, should check SDCBUSY */
-               while ((readl(host->base + SDC_STS) & SDC_STS_SDCBUSY) &&
-                               time_before(jiffies, tmo))
-                       cpu_relax();
-               if (readl(host->base + SDC_STS) & SDC_STS_SDCBUSY) {
+               ret = readl_poll_timeout_atomic(host->base + SDC_STS, val,
+                                               !(val & SDC_STS_SDCBUSY), 1, 20000);
+               if (ret) {
                        dev_err(host->dev, "Controller busy detected\n");
                        host->error |= REQ_CMD_BUSY;
                        msdc_cmd_done(host, MSDC_INT_CMDTMO, mrq, cmd);
@@ -1367,6 +1365,8 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
            (MSDC_INT_XFER_COMPL | MSDC_INT_DATCRCERR | MSDC_INT_DATTMO
             | MSDC_INT_DMA_BDCSERR | MSDC_INT_DMA_GPDCSERR
             | MSDC_INT_DMA_PROTECT);
+       u32 val;
+       int ret;
 
        spin_lock_irqsave(&host->lock, flags);
        done = !host->data;
@@ -1383,8 +1383,14 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
                                readl(host->base + MSDC_DMA_CFG));
                sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP,
                                1);
-               while (readl(host->base + MSDC_DMA_CFG) & MSDC_DMA_CFG_STS)
-                       cpu_relax();
+
+               ret = readl_poll_timeout_atomic(host->base + MSDC_DMA_CFG, val,
+                                               !(val & MSDC_DMA_CFG_STS), 1, 20000);
+               if (ret) {
+                       dev_dbg(host->dev, "DMA stop timed out\n");
+                       return false;
+               }
+
                sdr_clr_bits(host->base + MSDC_INTEN, data_ints_mask);
                dev_dbg(host->dev, "DMA stop\n");
 
@@ -2598,7 +2604,11 @@ static int msdc_drv_probe(struct platform_device *pdev)
        spin_lock_init(&host->lock);
 
        platform_set_drvdata(pdev, mmc);
-       msdc_ungate_clock(host);
+       ret = msdc_ungate_clock(host);
+       if (ret) {
+               dev_err(&pdev->dev, "Cannot ungate clocks!\n");
+               goto release_mem;
+       }
        msdc_init_hw(host);
 
        if (mmc->caps2 & MMC_CAP2_CQE) {
@@ -2757,8 +2767,12 @@ static int __maybe_unused msdc_runtime_resume(struct device *dev)
 {
        struct mmc_host *mmc = dev_get_drvdata(dev);
        struct msdc_host *host = mmc_priv(mmc);
+       int ret;
+
+       ret = msdc_ungate_clock(host);
+       if (ret)
+               return ret;
 
-       msdc_ungate_clock(host);
        msdc_restore_reg(host);
        return 0;
 }