summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (from parent 1: a9da1c1)
raw | patch | inline | side by side (from parent 1: a9da1c1)
author | Dave Gerlach <d-gerlach@ti.com> | |
Fri, 2 Nov 2018 10:30:46 +0000 (16:00 +0530) | ||
committer | Tero Kristo <t-kristo@ti.com> | |
Tue, 6 Nov 2018 13:26:12 +0000 (15:26 +0200) |
It is possible that when suspending the clock event timer it will generate
an interrupt just before their suspend is completed, but after interrupts have
been disabled. In this case any pending interrupts will prevent suspend, so
ACK the timer interrupt to avoid this.
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
an interrupt just before their suspend is completed, but after interrupts have
been disabled. In this case any pending interrupts will prevent suspend, so
ACK the timer interrupt to avoid this.
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
arch/arm/mach-omap2/timer.c | patch | blob | history |
index 98ed5ac073bc1fcaac2a4394b6f01a677d461118..37c0444564a342fcdeeaf13828724eedd60707bb 100644 (file)
/* Clockevent hwmod for am335x and am437x suspend */
static struct omap_hwmod *clockevent_gpt_hwmod;
+static struct irq_chip *clkev_irq_chip;
+static struct irq_desc *clkev_irq_desc;
/* Clockesource hwmod for am437x suspend */
static struct omap_hwmod *clocksource_gpt_hwmod;
return 0;
}
+static void omap_clkevt_late_ack(void)
+{
+ if (!clkev_irq_chip)
+ return;
+
+ if (clkev_irq_chip->irq_ack)
+ clkev_irq_chip->irq_ack(&clkev_irq_desc->irq_data);
+ if (clkev_irq_chip->irq_eoi)
+ clkev_irq_chip->irq_eoi(&clkev_irq_desc->irq_data);
+
+ clkev_irq_chip->irq_unmask(&clkev_irq_desc->irq_data);
+}
+
static void omap_clkevt_idle(struct clock_event_device *unused)
{
if (!clockevent_gpt_hwmod)
return;
+ /*
+ * It is possible for a late interrupt to be generated which will
+ * cause a suspend failure. Let's ack it here both in the timer
+ * and the interrupt controller to avoid this.
+ */
+ __omap_dm_timer_write_status(&clkev, OMAP_TIMER_INT_OVERFLOW);
+ omap_clkevt_late_ack();
+
omap_hwmod_idle(clockevent_gpt_hwmod);
}
clockevent_gpt_hwmod =
omap_hwmod_lookup(clockevent_gpt.name);
+
+ clkev_irq_desc = irq_to_desc(clkev.irq);
+ if (clkev_irq_desc)
+ clkev_irq_chip = irq_desc_get_chip(clkev_irq_desc);
}
pr_info("OMAP clockevent source: %s at %lu Hz\n", clockevent_gpt.name,