diff options
author | Colin Cross <ccross@android.com> | 2011-04-29 16:59:29 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:34:23 -0800 |
commit | 31867e6e2bf11be593b0282eb5e873319fc774f3 (patch) | |
tree | eda966a578fa13a8d9b08534a4c59216a35da66a /arch/arm/mach-tegra/timer.c | |
parent | c0e115b08c4528b9bc86d6e4be92043cb09c8c42 (diff) |
ARM: tegra: timer: Add suspend and resume support
Change-Id: I4d431037e83742e123ad81e4614354b14e32d453
Signed-off-by: Colin Cross <ccross@android.com>
Diffstat (limited to 'arch/arm/mach-tegra/timer.c')
-rw-r--r-- | arch/arm/mach-tegra/timer.c | 70 |
1 files changed, 39 insertions, 31 deletions
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c index cb83ca8a7d37..732a60cab93f 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/arch/arm/mach-tegra/timer.c @@ -60,6 +60,8 @@ static void __iomem *rtc_base = IO_ADDRESS(TEGRA_RTC_BASE); static struct timespec persistent_ts; static u64 persistent_ms, last_persistent_ms; +static u32 usec_offset; +static bool usec_suspended; #define timer_writel(value, reg) \ __raw_writel(value, (u32)timer_reg_base + (reg)) @@ -115,15 +117,23 @@ static DEFINE_CLOCK_DATA(cd); #define SC_MULT 4194304000u #define SC_SHIFT 22 +static u32 notrace tegra_read_usec(void) +{ + u32 cyc = usec_offset; + if (!usec_suspended) + cyc += timer_readl(TIMERUS_CNTR_1US); + return cyc; +} + unsigned long long notrace sched_clock(void) { - u32 cyc = timer_readl(TIMERUS_CNTR_1US); + u32 cyc = tegra_read_usec(); return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); } static void notrace tegra_update_sched_clock(void) { - u32 cyc = timer_readl(TIMERUS_CNTR_1US); + u32 cyc = tegra_read_usec(); update_sched_clock(&cd, cyc, (u32)~0); } @@ -179,6 +189,31 @@ static struct irqaction tegra_timer_irq = { .irq = INT_TMR3, }; +static u32 usec_config; + +static int tegra_timer_suspend(void) +{ + usec_config = timer_readl(TIMERUS_USEC_CFG); + + usec_offset += timer_readl(TIMERUS_CNTR_1US); + usec_suspended = true; + + return 0; +} + +static void tegra_timer_resume(void) +{ + timer_writel(usec_config, TIMERUS_USEC_CFG); + + usec_offset -= timer_readl(TIMERUS_CNTR_1US); + usec_suspended = false; +} + +static struct syscore_ops tegra_timer_syscore_ops = { + .suspend = tegra_timer_suspend, + .resume = tegra_timer_resume, +}; + static void __init tegra_init_timer(void) { struct clk *clk; @@ -241,37 +276,10 @@ static void __init tegra_init_timer(void) tegra_clockevent.cpumask = cpu_all_mask; tegra_clockevent.irq = tegra_timer_irq.irq; clockevents_register_device(&tegra_clockevent); + + register_syscore_ops(&tegra_timer_syscore_ops); } struct sys_timer tegra_timer = { .init = tegra_init_timer, }; - -#ifdef CONFIG_PM -static u32 usec_config; - -static int tegra_timer_suspend(void) -{ - usec_config = timer_readl(TIMERUS_USEC_CFG); - - return 0; -} - -static void tegra_timer_resume(void) -{ - timer_writel(usec_config, TIMERUS_USEC_CFG); -} - -static struct syscore_ops tegra_timer_syscore_ops = { - .suspend = tegra_timer_suspend, - .resume = tegra_timer_resume, -}; - -static int tegra_timer_syscore_init(void) -{ - register_syscore_ops(&tegra_timer_syscore_ops); - - return 0; -} -subsys_initcall(tegra_timer_syscore_init); -#endif |