The low-level read and write access routines wait on write-pending register
in posted mode to make sure that previous write is complete on respective
registers. This waiting is done in an infinite while loop. Now it is being
modified to use timeout instead.

Signed-off-by: Tarun Kanti DebBarma <tarun.ka...@ti.com>
Reviewed-by: Varadarajan, Charulatha <ch...@ti.com>
Acked-by: Cousson, Benoit <b-cous...@ti.com>
---
 arch/arm/plat-omap/dmtimer.c |   33 +++++++++++++++++++++++++--------
 1 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index fcac422..a39d5ba 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -43,6 +43,7 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <plat/dmtimer.h>
+#include <plat/common.h>
 
 /* register offsets */
 #define _OMAP_TIMER_ID_OFFSET          0x00
@@ -153,6 +154,8 @@
 #define OMAP_TIMER_TICK_INT_MASK_COUNT_REG                             \
                (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
 
+#define MAX_WRITE_PEND_WAIT            10000 /* 10ms timeout delay */
+
 static LIST_HEAD(omap_timer_list);
 static DEFINE_SPINLOCK(dm_timer_lock);
 
@@ -168,16 +171,23 @@ static DEFINE_SPINLOCK(dm_timer_lock);
 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
 {
        struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+       int i = 0;
 
        if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
                reg += pdata->func_offset;
        else if (reg >= OMAP_TIMER_STAT_REG)
                reg += pdata->intr_offset;
 
-       if (timer->posted)
-               while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 
0xff))
-                               & (reg >> WPSHIFT))
-                       cpu_relax();
+       if (timer->posted) {
+               omap_test_timeout(!(readl(timer->io_base +
+                       ((OMAP_TIMER_WRITE_PEND_REG +
+                       pdata->func_offset) & 0xff)) & (reg >> WPSHIFT)),
+                       MAX_WRITE_PEND_WAIT, i);
+
+               if (WARN_ON_ONCE(i == MAX_WRITE_PEND_WAIT))
+                       pr_err(": read timeout\n");
+       }
+
        return readl(timer->io_base + (reg & 0xff));
 }
 
@@ -195,16 +205,23 @@ static void omap_dm_timer_write_reg(struct omap_dm_timer 
*timer, u32 reg,
                                                u32 value)
 {
        struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
+       int i = 0;
 
        if (reg >= OMAP_TIMER_WAKEUP_EN_REG)
                reg += pdata->func_offset;
        else if (reg >= OMAP_TIMER_STAT_REG)
                reg += pdata->intr_offset;
 
-       if (timer->posted)
-               while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 
0xff))
-                               & (reg >> WPSHIFT))
-                       cpu_relax();
+       if (timer->posted) {
+               omap_test_timeout(!(readl(timer->io_base +
+                       ((OMAP_TIMER_WRITE_PEND_REG +
+                       pdata->func_offset) & 0xff)) & (reg >> WPSHIFT)),
+                       MAX_WRITE_PEND_WAIT, i);
+
+               if (WARN_ON(i == MAX_WRITE_PEND_WAIT))
+                       pr_err(": write timeout\n");
+       }
+
        writel(value, timer->io_base + (reg & 0xff));
 }
 
-- 
1.6.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to