aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/i2c/i2c-uniphier-f.c34
1 files changed, 10 insertions, 24 deletions
diff --git a/drivers/i2c/i2c-uniphier-f.c b/drivers/i2c/i2c-uniphier-f.c
index e212c13e69f..9f0df599a03 100644
--- a/drivers/i2c/i2c-uniphier-f.c
+++ b/drivers/i2c/i2c-uniphier-f.c
@@ -9,6 +9,7 @@
#include <common.h>
#include <linux/types.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/sizes.h>
#include <linux/errno.h>
#include <dm/device.h>
@@ -69,26 +70,14 @@ struct uniphier_fi2c_dev {
unsigned long timeout; /* time out (us) */
};
-static int poll_status(u32 __iomem *reg, u32 flag)
-{
- int wait = 1000000; /* 1 sec is long enough */
-
- while (readl(reg) & flag) {
- if (wait-- < 0)
- return -EREMOTEIO;
- udelay(1);
- }
-
- return 0;
-}
-
static int reset_bus(struct uniphier_fi2c_regs __iomem *regs)
{
+ u32 val;
int ret;
/* bus forcible reset */
writel(I2C_RST_RST, &regs->rst);
- ret = poll_status(&regs->rst, I2C_RST_RST);
+ ret = readl_poll_timeout(&regs->rst, val, !(val & I2C_RST_RST), 1);
if (ret < 0)
debug("error: fail to reset I2C controller\n");
@@ -97,9 +86,10 @@ static int reset_bus(struct uniphier_fi2c_regs __iomem *regs)
static int check_device_busy(struct uniphier_fi2c_regs __iomem *regs)
{
+ u32 val;
int ret;
- ret = poll_status(&regs->sr, I2C_SR_DB);
+ ret = readl_poll_timeout(&regs->sr, val, !(val & I2C_SR_DB), 100);
if (ret < 0) {
debug("error: device busy too long. reset...\n");
ret = reset_bus(regs);
@@ -138,15 +128,11 @@ static int wait_for_irq(struct uniphier_fi2c_dev *dev, u32 flags,
bool *stop)
{
u32 irq;
- unsigned long wait = dev->timeout;
- int ret = -EREMOTEIO;
-
- do {
- udelay(1);
- irq = readl(&dev->regs->intr);
- } while (!(irq & flags) && wait--);
+ int ret;
- if (wait < 0) {
+ ret = readl_poll_timeout(&dev->regs->intr, irq, irq & flags,
+ dev->timeout);
+ if (ret < 0) {
debug("error: time out\n");
return ret;
}
@@ -172,7 +158,7 @@ static int issue_stop(struct uniphier_fi2c_dev *dev, int old_ret)
debug("stop condition\n");
writel(I2C_CR_MST | I2C_CR_STO, &dev->regs->cr);
- ret = poll_status(&dev->regs->sr, I2C_SR_DB);
+ ret = check_device_busy(dev->regs);
if (ret < 0)
debug("error: device busy after operation\n");