diff options
-rw-r--r-- | drivers/mmc/host/bcm2835.c | 37 |
1 files changed, 16 insertions, 21 deletions
diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c index 64a233416ad9..e8a3f6e3042f 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c @@ -31,6 +31,7 @@ #include <linux/err.h> #include <linux/highmem.h> #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/module.h> #include <linux/of_address.h> #include <linux/of_irq.h> @@ -609,33 +610,27 @@ static void bcm2835_prepare_data(struct bcm2835_host *host, writel(data->blocks, host->ioaddr + SDHBLC); } -static u32 bcm2835_read_wait_sdcmd(struct bcm2835_host *host, u32 timeout, +static u32 bcm2835_read_wait_sdcmd(struct bcm2835_host *host, u32 max_ms, bool check_fail) { struct device *dev = &host->pdev->dev; - unsigned long start = jiffies; - unsigned long fastpoll = start + usecs_to_jiffies(10); - unsigned long end = start + msecs_to_jiffies(timeout); u32 value; + int ret; - for (;;) { - value = readl(host->ioaddr + SDCMD); - if (!(value & SDCMD_NEW_FLAG)) - break; - if (check_fail && (value & SDCMD_FAIL_FLAG)) - break; - if (time_after(jiffies, end)) { - dev_err(dev, "%s: timeout (%d us)\n", - __func__, timeout); - break; - } + ret = readl_poll_timeout(host->ioaddr + SDCMD, value, + (!(value & SDCMD_NEW_FLAG)) || + (check_fail && (value & SDCMD_FAIL_FLAG)), + 1, 10); + if (ret == -ETIMEDOUT) + /* if it takes a while make poll interval bigger */ + ret = readl_poll_timeout(host->ioaddr + SDCMD, value, + (!(value & SDCMD_NEW_FLAG)) || + (check_fail && (value & SDCMD_FAIL_FLAG)), + 10, max_ms * 1000); + if (ret == -ETIMEDOUT) + dev_err(dev, "%s: timeout (%d ms)\n", + __func__, max_ms); - /* if it takes longer reduce poll interval */ - if (time_after(jiffies, fastpoll)) - udelay(10); - else - cpu_relax(); - } return value; } |