diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 78b7712..8b0068c 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -332,6 +332,10 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
 	if (posted)
 		omap_dm_timer_enable_posted(timer);
 
+	/* Check that the intended posted configuration matches the actual */
+	if (posted != timer->posted)
+		return -EINVAL;
+
 	timer->rate = clk_get_rate(timer->fclk);
 	timer->reserved = 1;
 
@@ -344,6 +348,15 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
 {
 	int res;
 
+	omap_dm_timer_populate_errata(&clkev);
+
+	/*
+	 * For clock-event timers we never read the timer counter and
+	 * so we are not impacted by errata i103 and i767. Therefore,
+	 * we can safely ignore this errata for clock-event timers.
+	 */
+	omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767);
+
 	res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property,
 				     OMAP_CLKEVT_POSTEDMODE);
 	BUG_ON(res);
@@ -472,6 +485,8 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id,
 {
 	int res;
 
+	omap_dm_timer_populate_errata(&clksrc);
+
 	res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL,
 				     OMAP_CLKSRC_POSTEDMODE);
 	BUG_ON(res);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 699570b..4abbbe5 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -177,6 +177,37 @@ int omap_dm_timer_reserve_systimer(int id)
 }
 
 /**
+ * omap_dm_timer_populate_errata - populate errata flags for a timer
+ * @timer:      pointer to timer handle
+ *
+ * For a given timer, populate the timer errata flags that are specific to the
+ * OMAP device being used.
+ */
+void omap_dm_timer_populate_errata(struct omap_dm_timer *timer)
+{
+	timer->errata = 0;
+
+	if (cpu_class_is_omap1() || cpu_is_omap24xx())
+		return;
+
+	timer->errata = OMAP_TIMER_ERRATA_I103_I767;
+}
+
+/**
+ * omap_dm_timer_override_errata - override errata flags for a timer
+ * @timer:      pointer to timer handle
+ * @errata:	errata flags to be ignored
+ *
+ * For a given timer, override a timer errata by clearing the flags specified
+ * by the errata argument. A specific erratum should only be overridden for a
+ * timer if the timer is used in such a way the erratum has no impact.
+ */
+void omap_dm_timer_override_errata(struct omap_dm_timer *timer, u32 errata)
+{
+	timer->errata &= ~errata;
+}
+
+/*
  * omap_dm_timer_enable_posted - enables write posted mode
  * @timer:      pointer to timer instance handle
  *
@@ -191,6 +222,9 @@ void omap_dm_timer_enable_posted(struct omap_dm_timer *timer)
 	if (timer->posted)
 		return;
 
+	if (timer->errata & OMAP_TIMER_ERRATA_I103_I767)
+		return;
+
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
 				OMAP_TIMER_CTRL_POSTED);
 	timer->context.tsicr = OMAP_TIMER_CTRL_POSTED;
@@ -824,6 +858,8 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
 	timer->irq = irq->start;
 	timer->pdev = pdev;
 
+	omap_dm_timer_populate_errata(timer);
+
 	/* Skip pm_runtime_enable for OMAP1 */
 	if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
 		pm_runtime_enable(dev);
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 2d0228f..ef93017 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -36,6 +36,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <plat/cpu.h>
 
 #ifndef __ASM_ARCH_DMTIMER_H
 #define __ASM_ARCH_DMTIMER_H
@@ -66,6 +67,16 @@
 #define OMAP_TIMER_NEEDS_RESET				0x10000000
 #define OMAP_TIMER_HAS_DSP_IRQ				0x08000000
 
+/*
+ * timer errata flags
+ *
+ * Errata i103/i767 impacts all OMAP3/4/5 devices including AM33xx. This
+ * errata prevents us from using posted mode on these devices, unless the
+ * timer counter register is never read. For more details please refer to
+ * the OMAP3/4/5 errata documents.
+ */
+#define OMAP_TIMER_ERRATA_I103_I767			0x80000000
+
 struct omap_timer_capability_dev_attr {
 	u32 timer_capability;
 };
@@ -101,6 +112,8 @@ struct dmtimer_platform_data {
 };
 
 int omap_dm_timer_reserve_systimer(int id);
+void omap_dm_timer_populate_errata(struct omap_dm_timer *timer);
+void omap_dm_timer_override_errata(struct omap_dm_timer *timer, u32 errata);
 void omap_dm_timer_enable_posted(struct omap_dm_timer *timer);
 struct omap_dm_timer *omap_dm_timer_request(void);
 struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
@@ -272,6 +285,7 @@ struct omap_dm_timer {
 	int ctx_loss_count;
 	int revision;
 	u32 capability;
+	u32 errata;
 	struct platform_device *pdev;
 	struct list_head node;
 };
