Commit b6d2d81c authored by Shawn Lin's avatar Shawn Lin Committed by Ulf Hansson

mmc: dw_mmc: improve the timeout polling code

Just use the readl_poll_timeout{_atomic} to avold open
coding them.
Signed-off-by: default avatarShawn Lin <shawn.lin@rock-chips.com>
Signed-off-by: default avatarJaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 5a7ad114
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -65,6 +66,8 @@ ...@@ -65,6 +66,8 @@
struct idmac_desc_64addr { struct idmac_desc_64addr {
u32 des0; /* Control Descriptor */ u32 des0; /* Control Descriptor */
#define IDMAC_OWN_CLR64(x) \
!((x) & cpu_to_le32(IDMAC_DES0_OWN))
u32 des1; /* Reserved */ u32 des1; /* Reserved */
...@@ -343,7 +346,7 @@ static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd) ...@@ -343,7 +346,7 @@ static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd)
static void dw_mci_wait_while_busy(struct dw_mci *host, u32 cmd_flags) static void dw_mci_wait_while_busy(struct dw_mci *host, u32 cmd_flags)
{ {
unsigned long timeout = jiffies + msecs_to_jiffies(500); u32 status;
/* /*
* Databook says that before issuing a new data transfer command * Databook says that before issuing a new data transfer command
...@@ -355,14 +358,11 @@ static void dw_mci_wait_while_busy(struct dw_mci *host, u32 cmd_flags) ...@@ -355,14 +358,11 @@ static void dw_mci_wait_while_busy(struct dw_mci *host, u32 cmd_flags)
*/ */
if ((cmd_flags & SDMMC_CMD_PRV_DAT_WAIT) && if ((cmd_flags & SDMMC_CMD_PRV_DAT_WAIT) &&
!(cmd_flags & SDMMC_CMD_VOLT_SWITCH)) { !(cmd_flags & SDMMC_CMD_VOLT_SWITCH)) {
while (mci_readl(host, STATUS) & SDMMC_STATUS_BUSY) { if (readl_poll_timeout_atomic(host->regs + SDMMC_STATUS,
if (time_after(jiffies, timeout)) { status,
/* Command will fail; we'll pass error then */ !(status & SDMMC_STATUS_BUSY),
dev_err(host->dev, "Busy; trying anyway\n"); 10, 500 * USEC_PER_MSEC))
break; dev_err(host->dev, "Busy; trying anyway\n");
}
udelay(10);
}
} }
} }
...@@ -555,7 +555,7 @@ static inline int dw_mci_prepare_desc64(struct dw_mci *host, ...@@ -555,7 +555,7 @@ static inline int dw_mci_prepare_desc64(struct dw_mci *host,
{ {
unsigned int desc_len; unsigned int desc_len;
struct idmac_desc_64addr *desc_first, *desc_last, *desc; struct idmac_desc_64addr *desc_first, *desc_last, *desc;
unsigned long timeout; u32 val;
int i; int i;
desc_first = desc_last = desc = host->sg_cpu; desc_first = desc_last = desc = host->sg_cpu;
...@@ -577,12 +577,10 @@ static inline int dw_mci_prepare_desc64(struct dw_mci *host, ...@@ -577,12 +577,10 @@ static inline int dw_mci_prepare_desc64(struct dw_mci *host,
* isn't still owned by IDMAC as IDMAC's write * isn't still owned by IDMAC as IDMAC's write
* ops and CPU's read ops are asynchronous. * ops and CPU's read ops are asynchronous.
*/ */
timeout = jiffies + msecs_to_jiffies(100); if (readl_poll_timeout_atomic(&desc->des0, val,
while (readl(&desc->des0) & IDMAC_DES0_OWN) { !(val & IDMAC_DES0_OWN),
if (time_after(jiffies, timeout)) 10, 100 * USEC_PER_MSEC))
goto err_own_bit; goto err_own_bit;
udelay(10);
}
/* /*
* Set the OWN bit and disable interrupts * Set the OWN bit and disable interrupts
...@@ -629,7 +627,7 @@ static inline int dw_mci_prepare_desc32(struct dw_mci *host, ...@@ -629,7 +627,7 @@ static inline int dw_mci_prepare_desc32(struct dw_mci *host,
{ {
unsigned int desc_len; unsigned int desc_len;
struct idmac_desc *desc_first, *desc_last, *desc; struct idmac_desc *desc_first, *desc_last, *desc;
unsigned long timeout; u32 val;
int i; int i;
desc_first = desc_last = desc = host->sg_cpu; desc_first = desc_last = desc = host->sg_cpu;
...@@ -651,13 +649,11 @@ static inline int dw_mci_prepare_desc32(struct dw_mci *host, ...@@ -651,13 +649,11 @@ static inline int dw_mci_prepare_desc32(struct dw_mci *host,
* isn't still owned by IDMAC as IDMAC's write * isn't still owned by IDMAC as IDMAC's write
* ops and CPU's read ops are asynchronous. * ops and CPU's read ops are asynchronous.
*/ */
timeout = jiffies + msecs_to_jiffies(100); if (readl_poll_timeout_atomic(&desc->des0, val,
while (readl(&desc->des0) & IDMAC_OWN_CLR64(val),
cpu_to_le32(IDMAC_DES0_OWN)) { 10,
if (time_after(jiffies, timeout)) 100 * USEC_PER_MSEC))
goto err_own_bit; goto err_own_bit;
udelay(10);
}
/* /*
* Set the OWN bit and disable interrupts * Set the OWN bit and disable interrupts
...@@ -1136,7 +1132,6 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) ...@@ -1136,7 +1132,6 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg) static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg)
{ {
struct dw_mci *host = slot->host; struct dw_mci *host = slot->host;
unsigned long timeout = jiffies + msecs_to_jiffies(500);
unsigned int cmd_status = 0; unsigned int cmd_status = 0;
mci_writel(host, CMDARG, arg); mci_writel(host, CMDARG, arg);
...@@ -1144,14 +1139,12 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg) ...@@ -1144,14 +1139,12 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg)
dw_mci_wait_while_busy(host, cmd); dw_mci_wait_while_busy(host, cmd);
mci_writel(host, CMD, SDMMC_CMD_START | cmd); mci_writel(host, CMD, SDMMC_CMD_START | cmd);
while (time_before(jiffies, timeout)) { if (readl_poll_timeout_atomic(host->regs + SDMMC_CMD, cmd_status,
cmd_status = mci_readl(host, CMD); !(cmd_status & SDMMC_CMD_START),
if (!(cmd_status & SDMMC_CMD_START)) 1, 500 * USEC_PER_MSEC))
return; dev_err(&slot->mmc->class_dev,
} "Timeout sending command (cmd %#x arg %#x status %#x)\n",
dev_err(&slot->mmc->class_dev, cmd, arg, cmd_status);
"Timeout sending command (cmd %#x arg %#x status %#x)\n",
cmd, arg, cmd_status);
} }
static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
...@@ -2832,7 +2825,6 @@ static void dw_mci_init_dma(struct dw_mci *host) ...@@ -2832,7 +2825,6 @@ static void dw_mci_init_dma(struct dw_mci *host)
static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset) static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset)
{ {
unsigned long timeout = jiffies + msecs_to_jiffies(500);
u32 ctrl; u32 ctrl;
ctrl = mci_readl(host, CTRL); ctrl = mci_readl(host, CTRL);
...@@ -2840,17 +2832,16 @@ static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset) ...@@ -2840,17 +2832,16 @@ static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset)
mci_writel(host, CTRL, ctrl); mci_writel(host, CTRL, ctrl);
/* wait till resets clear */ /* wait till resets clear */
do { if (readl_poll_timeout_atomic(host->regs + SDMMC_CTRL, ctrl,
ctrl = mci_readl(host, CTRL); !(ctrl & reset),
if (!(ctrl & reset)) 1, 500 * USEC_PER_MSEC)) {
return true; dev_err(host->dev,
} while (time_before(jiffies, timeout)); "Timeout resetting block (ctrl reset %#x)\n",
ctrl & reset);
dev_err(host->dev, return false;
"Timeout resetting block (ctrl reset %#x)\n", }
ctrl & reset);
return false; return true;
} }
static bool dw_mci_reset(struct dw_mci *host) static bool dw_mci_reset(struct dw_mci *host)
...@@ -2879,17 +2870,12 @@ static bool dw_mci_reset(struct dw_mci *host) ...@@ -2879,17 +2870,12 @@ static bool dw_mci_reset(struct dw_mci *host)
/* if using dma we wait for dma_req to clear */ /* if using dma we wait for dma_req to clear */
if (host->use_dma) { if (host->use_dma) {
unsigned long timeout = jiffies + msecs_to_jiffies(500);
u32 status; u32 status;
do { if (readl_poll_timeout_atomic(host->regs + SDMMC_STATUS,
status = mci_readl(host, STATUS); status,
if (!(status & SDMMC_STATUS_DMA_REQ)) !(status & SDMMC_STATUS_DMA_REQ),
break; 1, 500 * USEC_PER_MSEC)) {
cpu_relax();
} while (time_before(jiffies, timeout));
if (status & SDMMC_STATUS_DMA_REQ) {
dev_err(host->dev, dev_err(host->dev,
"%s: Timeout waiting for dma_req to clear during reset\n", "%s: Timeout waiting for dma_req to clear during reset\n",
__func__); __func__);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment