[PATCH 2/3] plat-nomadik: Added suspend/resume support for MTU timer.
Jonas Aaberg
jonas.aberg at stericsson.com
Thu Sep 2 03:30:32 EDT 2010
Acked-by: Linus Walleij <linus.walleij at stericsson.com>
Acked-by: Alessandro Rubini <rubini at unipv.it>
Signed-off-by: Jonas Aaberg <jonas.aberg at stericsson.com>
---
arch/arm/plat-nomadik/timer.c | 80 ++++++++++++++++++++++++++++++-----------
1 files changed, 59 insertions(+), 21 deletions(-)
diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c
index d673888..7d2d965 100644
--- a/arch/arm/plat-nomadik/timer.c
+++ b/arch/arm/plat-nomadik/timer.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-nomadik/timer.c
+ * linux/arch/arm/plat-nomadik/timer.c
*
* Copyright (C) 2008 STMicroelectronics
* Copyright (C) 2010 Alessandro Rubini
@@ -75,7 +75,7 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode,
cr = readl(mtu_base + MTU_CR(1));
writel(0, mtu_base + MTU_LR(1));
writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(1));
- writel(0x2, mtu_base + MTU_IMSC);
+ writel(1 << 1, mtu_base + MTU_IMSC);
break;
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_UNUSED:
@@ -127,36 +127,78 @@ static struct irqaction nmdk_timer_irq = {
.dev_id = &nmdk_clkevt,
};
+static void nmdk_timer_reset(void)
+{
+ u32 cr = MTU_CRn_32BITS | MTU_CRn_ENA;
+ struct clk *clk0;
+
+ clk0 = clk_get_sys("mtu0", NULL);
+
+ clk_enable(clk0);
+
+ if (clk_get_rate(clk0) > (16 << 20))
+ cr |= MTU_CRn_PRESCALE_16;
+ else
+ cr |= MTU_CRn_PRESCALE_1;
+
+ /* Timer 0, the free running clocksource */
+ writel(0, mtu_base + MTU_CR(0));
+ writel(0, mtu_base + MTU_LR(0));
+ writel(0, mtu_base + MTU_BGLR(0));
+ writel(cr, mtu_base + MTU_CR(0));
+
+ /* Timer 1, clock event */
+ writel(0, mtu_base + MTU_CR(1));
+ writel(0, mtu_base + MTU_LR(1));
+ writel(1 << 1, mtu_base + MTU_IMSC);
+ writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1));
+}
+
+#ifdef CONFIG_PM
+void nmdk_timer_suspend(void)
+{
+ struct clk *clk0;
+
+ /* No interrupts */
+ writel(0, mtu_base + MTU_IMSC);
+ /* Off */
+ writel(0, mtu_base + MTU_CR(0));
+ writel(0, mtu_base + MTU_CR(1));
+
+ clk0 = clk_get_sys("mtu0", NULL);
+
+ clk_disable(clk0);
+}
+
+void nmdk_timer_resume(void)
+{
+ nmdk_timer_reset();
+}
+#endif
+
void __init nmdk_timer_init(void)
{
unsigned long rate;
struct clk *clk0;
- u32 cr;
+ /*
+ * On MTU block 0: timer0 is used as source,
+ * timer1 is used for events.
+ */
clk0 = clk_get_sys("mtu0", NULL);
BUG_ON(IS_ERR(clk0));
- clk_enable(clk0);
-
/*
- * Tick rate is 2.4MHz for Nomadik and 110MHz for ux500:
+ * Tick rate is 2.4MHz for Nomadik and 100 or 133MHz for ux500:
* use a divide-by-16 counter if it's more than 16MHz
*/
- cr = MTU_CRn_32BITS;;
rate = clk_get_rate(clk0);
- if (rate > 16 << 20) {
+ if (rate > (16 << 20))
rate /= 16;
- cr |= MTU_CRn_PRESCALE_16;
- } else {
- cr |= MTU_CRn_PRESCALE_1;
- }
+
clocksource_calc_mult_shift(&nmdk_clksrc, rate, MTU_MIN_RANGE);
- /* Timer 0 is the free running clocksource */
- writel(cr, mtu_base + MTU_CR(0));
- writel(0, mtu_base + MTU_LR(0));
- writel(0, mtu_base + MTU_BGLR(0));
- writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
+ nmdk_timer_reset();
/* Now the scheduling clock is ready */
nmdk_clksrc.read = nmdk_read_timer;
@@ -165,12 +207,8 @@ void __init nmdk_timer_init(void)
pr_err("timer: failed to initialize clock source %s\n",
nmdk_clksrc.name);
- /* Timer 1 is used for events */
-
clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE);
- writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */
-
nmdk_clkevt.max_delta_ns =
clockevent_delta2ns(0xffffffff, &nmdk_clkevt);
nmdk_clkevt.min_delta_ns =
--
1.6.3.3
More information about the linux-arm-kernel
mailing list