@@ -41,6 +41,7 @@
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/err.h>
+#include <plat/common.h>
#include <plat/dmtimer.h>
/* register offsets */
@@ -152,6 +153,7 @@
#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 +170,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 +204,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));
}