mmc: mtk-sd: Use readl_poll_timeout instead of open-coded polling
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>
This commit is contained in:
parent
585cba9d42
commit
ffaea6ebfe
@ -636,12 +636,11 @@ static void msdc_reset_hw(struct msdc_host *host)
|
|||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_RST);
|
sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_RST);
|
||||||
while (readl(host->base + MSDC_CFG) & MSDC_CFG_RST)
|
readl_poll_timeout(host->base + MSDC_CFG, val, !(val & MSDC_CFG_RST), 0, 0);
|
||||||
cpu_relax();
|
|
||||||
|
|
||||||
sdr_set_bits(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
|
sdr_set_bits(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
|
||||||
while (readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_CLR)
|
readl_poll_timeout(host->base + MSDC_FIFOCS, val,
|
||||||
cpu_relax();
|
!(val & MSDC_FIFOCS_CLR), 0, 0);
|
||||||
|
|
||||||
val = readl(host->base + MSDC_INT);
|
val = readl(host->base + MSDC_INT);
|
||||||
writel(val, host->base + MSDC_INT);
|
writel(val, host->base + MSDC_INT);
|
||||||
@ -814,8 +813,9 @@ static void msdc_gate_clock(struct msdc_host *host)
|
|||||||
clk_disable_unprepare(host->h_clk);
|
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;
|
int ret;
|
||||||
|
|
||||||
clk_prepare_enable(host->h_clk);
|
clk_prepare_enable(host->h_clk);
|
||||||
@ -825,11 +825,11 @@ static void msdc_ungate_clock(struct msdc_host *host)
|
|||||||
ret = clk_bulk_prepare_enable(MSDC_NR_CLOCKS, host->bulk_clks);
|
ret = clk_bulk_prepare_enable(MSDC_NR_CLOCKS, host->bulk_clks);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(host->dev, "Cannot enable pclk/axi/ahb clock gates\n");
|
dev_err(host->dev, "Cannot enable pclk/axi/ahb clock gates\n");
|
||||||
return;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
|
return readl_poll_timeout(host->base + MSDC_CFG, val,
|
||||||
cpu_relax();
|
(val & MSDC_CFG_CKSTB), 1, 20000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
|
static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
|
||||||
@ -840,6 +840,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
|
|||||||
u32 div;
|
u32 div;
|
||||||
u32 sclk;
|
u32 sclk;
|
||||||
u32 tune_reg = host->dev_comp->pad_tune_reg;
|
u32 tune_reg = host->dev_comp->pad_tune_reg;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
if (!hz) {
|
if (!hz) {
|
||||||
dev_dbg(host->dev, "set mclk to 0\n");
|
dev_dbg(host->dev, "set mclk to 0\n");
|
||||||
@ -920,8 +921,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
|
|||||||
else
|
else
|
||||||
clk_prepare_enable(clk_get_parent(host->src_clk));
|
clk_prepare_enable(clk_get_parent(host->src_clk));
|
||||||
|
|
||||||
while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
|
readl_poll_timeout(host->base + MSDC_CFG, val, (val & MSDC_CFG_CKSTB), 0, 0);
|
||||||
cpu_relax();
|
|
||||||
sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
|
sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
|
||||||
mmc->actual_clock = sclk;
|
mmc->actual_clock = sclk;
|
||||||
host->mclk = hz;
|
host->mclk = hz;
|
||||||
@ -1231,13 +1231,13 @@ static bool msdc_cmd_done(struct msdc_host *host, int events,
|
|||||||
static inline bool msdc_cmd_is_ready(struct msdc_host *host,
|
static inline bool msdc_cmd_is_ready(struct msdc_host *host,
|
||||||
struct mmc_request *mrq, struct mmc_command *cmd)
|
struct mmc_request *mrq, struct mmc_command *cmd)
|
||||||
{
|
{
|
||||||
/* The max busy time we can endure is 20ms */
|
u32 val;
|
||||||
unsigned long tmo = jiffies + msecs_to_jiffies(20);
|
int ret;
|
||||||
|
|
||||||
while ((readl(host->base + SDC_STS) & SDC_STS_CMDBUSY) &&
|
/* The max busy time we can endure is 20ms */
|
||||||
time_before(jiffies, tmo))
|
ret = readl_poll_timeout_atomic(host->base + SDC_STS, val,
|
||||||
cpu_relax();
|
!(val & SDC_STS_CMDBUSY), 1, 20000);
|
||||||
if (readl(host->base + SDC_STS) & SDC_STS_CMDBUSY) {
|
if (ret) {
|
||||||
dev_err(host->dev, "CMD bus busy detected\n");
|
dev_err(host->dev, "CMD bus busy detected\n");
|
||||||
host->error |= REQ_CMD_BUSY;
|
host->error |= REQ_CMD_BUSY;
|
||||||
msdc_cmd_done(host, MSDC_INT_CMDTMO, mrq, cmd);
|
msdc_cmd_done(host, MSDC_INT_CMDTMO, mrq, cmd);
|
||||||
@ -1245,12 +1245,10 @@ static inline bool msdc_cmd_is_ready(struct msdc_host *host,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mmc_resp_type(cmd) == MMC_RSP_R1B || cmd->data) {
|
if (mmc_resp_type(cmd) == MMC_RSP_R1B || cmd->data) {
|
||||||
tmo = jiffies + msecs_to_jiffies(20);
|
|
||||||
/* R1B or with data, should check SDCBUSY */
|
/* R1B or with data, should check SDCBUSY */
|
||||||
while ((readl(host->base + SDC_STS) & SDC_STS_SDCBUSY) &&
|
ret = readl_poll_timeout_atomic(host->base + SDC_STS, val,
|
||||||
time_before(jiffies, tmo))
|
!(val & SDC_STS_SDCBUSY), 1, 20000);
|
||||||
cpu_relax();
|
if (ret) {
|
||||||
if (readl(host->base + SDC_STS) & SDC_STS_SDCBUSY) {
|
|
||||||
dev_err(host->dev, "Controller busy detected\n");
|
dev_err(host->dev, "Controller busy detected\n");
|
||||||
host->error |= REQ_CMD_BUSY;
|
host->error |= REQ_CMD_BUSY;
|
||||||
msdc_cmd_done(host, MSDC_INT_CMDTMO, mrq, cmd);
|
msdc_cmd_done(host, MSDC_INT_CMDTMO, mrq, cmd);
|
||||||
@ -1376,6 +1374,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_XFER_COMPL | MSDC_INT_DATCRCERR | MSDC_INT_DATTMO
|
||||||
| MSDC_INT_DMA_BDCSERR | MSDC_INT_DMA_GPDCSERR
|
| MSDC_INT_DMA_BDCSERR | MSDC_INT_DMA_GPDCSERR
|
||||||
| MSDC_INT_DMA_PROTECT);
|
| MSDC_INT_DMA_PROTECT);
|
||||||
|
u32 val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
spin_lock_irqsave(&host->lock, flags);
|
spin_lock_irqsave(&host->lock, flags);
|
||||||
done = !host->data;
|
done = !host->data;
|
||||||
@ -1392,8 +1392,14 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
|
|||||||
readl(host->base + MSDC_DMA_CFG));
|
readl(host->base + MSDC_DMA_CFG));
|
||||||
sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP,
|
sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP,
|
||||||
1);
|
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);
|
sdr_clr_bits(host->base + MSDC_INTEN, data_ints_mask);
|
||||||
dev_dbg(host->dev, "DMA stop\n");
|
dev_dbg(host->dev, "DMA stop\n");
|
||||||
|
|
||||||
@ -2674,7 +2680,11 @@ static int msdc_drv_probe(struct platform_device *pdev)
|
|||||||
spin_lock_init(&host->lock);
|
spin_lock_init(&host->lock);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, mmc);
|
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);
|
msdc_init_hw(host);
|
||||||
|
|
||||||
if (mmc->caps2 & MMC_CAP2_CQE) {
|
if (mmc->caps2 & MMC_CAP2_CQE) {
|
||||||
@ -2833,8 +2843,12 @@ static int __maybe_unused msdc_runtime_resume(struct device *dev)
|
|||||||
{
|
{
|
||||||
struct mmc_host *mmc = dev_get_drvdata(dev);
|
struct mmc_host *mmc = dev_get_drvdata(dev);
|
||||||
struct msdc_host *host = mmc_priv(mmc);
|
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);
|
msdc_restore_reg(host);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user