diff options
author | Dan Willemsen <dwillemsen@nvidia.com> | 2011-06-13 18:42:28 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:46:45 -0800 |
commit | adf27214e7c5b669adda02dfc1a483b48f876008 (patch) | |
tree | 8ac225d3f6598a0b877cf44e9d44040968a94d81 /arch/arm/mach-tegra/timer-t3.c | |
parent | 3c152b307286a4a32d2daeb3ca5e2caed646f795 (diff) |
HACKY: timer-t3 updates for K39
Rebase-Id: Re2ca6bafa842d114859a40c7ab19097fd86fc635
Diffstat (limited to 'arch/arm/mach-tegra/timer-t3.c')
-rw-r--r-- | arch/arm/mach-tegra/timer-t3.c | 112 |
1 files changed, 79 insertions, 33 deletions
diff --git a/arch/arm/mach-tegra/timer-t3.c b/arch/arm/mach-tegra/timer-t3.c index 629438869bf7..18f68649777e 100644 --- a/arch/arm/mach-tegra/timer-t3.c +++ b/arch/arm/mach-tegra/timer-t3.c @@ -19,6 +19,8 @@ */ #include <linux/init.h> +#include <linux/err.h> +#include <linux/sched.h> #include <linux/time.h> #include <linux/interrupt.h> #include <linux/irq.h> @@ -26,19 +28,18 @@ #include <linux/clocksource.h> #include <linux/clk.h> #include <linux/io.h> -#include <linux/cnt32_to_63.h> #include <linux/smp.h> +#include <linux/syscore_ops.h> #include <asm/mach/time.h> -#include <asm/mach/time.h> #include <asm/localtimer.h> +#include <asm/sched_clock.h> #include <mach/iomap.h> #include <mach/irqs.h> #include "board.h" #include "clock.h" -#include "pm.h" /* * Timers usage: @@ -75,15 +76,16 @@ static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE); 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)) #define timer_readl(reg) \ __raw_readl((u32)timer_reg_base + (reg)) -static u64 tegra_sched_clock_offset; -static u64 tegra_sched_clock_suspend_val; -static u64 tegra_sched_clock_suspend_rtc; - static int tegra_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { @@ -137,24 +139,33 @@ static struct clocksource tegra_clocksource = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -unsigned long long sched_clock(void) +static DEFINE_CLOCK_DATA(cd); + +/* TODO: is this right for Tegra3? + * Constants generated by clocks_calc_mult_shift(m, s, 1MHz, NSEC_PER_SEC, 60). + * This gives a resolution of about 1us and a wrap period of about 1h11min. + */ +#define SC_MULT 4194304000u +#define SC_SHIFT 22 + +static u32 notrace tegra_read_usec(void) { - return tegra_sched_clock_offset + - cnt32_to_63(timer_readl(TIMERUS_CNTR_1US)) * NSEC_PER_USEC; + u32 cyc = usec_offset; + if (!usec_suspended) + cyc += timer_readl(TIMERUS_CNTR_1US); + return cyc; } -static void tegra_sched_clock_suspend(void) +unsigned long long notrace sched_clock(void) { - tegra_sched_clock_suspend_val = sched_clock(); - tegra_sched_clock_suspend_rtc = tegra_rtc_read_ms(); + u32 cyc = tegra_read_usec(); + return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); } -static void tegra_sched_clock_resume(void) +static void notrace tegra_update_sched_clock(void) { - u64 rtc_offset_ms = tegra_rtc_read_ms() - tegra_sched_clock_suspend_rtc; - tegra_sched_clock_offset = tegra_sched_clock_suspend_val + - rtc_offset_ms * NSEC_PER_MSEC - - (sched_clock() - tegra_sched_clock_offset); + u32 cyc = tegra_read_usec(); + update_sched_clock(&cd, cyc, (u32)~0); } /* @@ -180,8 +191,6 @@ u64 tegra_rtc_read_ms(void) * tegra_rtc driver could be executing to avoid race conditions * on the RTC shadow register */ -static struct timespec persistent_ts; -static u64 persistent_ms, last_persistent_ms; void read_persistent_clock(struct timespec *ts) { u64 delta; @@ -211,6 +220,32 @@ static struct irqaction tegra_timer_irq = { .irq = INT_TMR1, }; +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, +}; + +#if 0 static int lp2_wake_timers[] = { TIMER3_OFFSET, TIMER4_OFFSET, @@ -292,14 +327,28 @@ static void test_lp2_wake_timers(void) #else static void test_lp2_wake_timers(void){} #endif +#endif static void __init tegra_init_timer(void) { + struct clk *clk; unsigned long rate = clk_measure_input_freq(); void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804; unsigned long id; int ret; + clk = clk_get_sys("timer", NULL); + BUG_ON(IS_ERR(clk)); + clk_enable(clk); + + /* + * rtc registers are used by read_persistent_clock, keep the rtc clock + * enabled + */ + clk = clk_get_sys("rtc-tegra", NULL); + BUG_ON(IS_ERR(clk)); + clk_enable(clk); + #ifdef CONFIG_HAVE_ARM_TWD twd_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x600); #endif @@ -330,6 +379,9 @@ static void __init tegra_init_timer(void) WARN(1, "Unknown clock rate"); } + init_fixed_sched_clock(&cd, tegra_update_sched_clock, 32, + 1000000, SC_MULT, SC_SHIFT); + if (clocksource_register_hz(&tegra_clocksource, 1000000)) { printk(KERN_ERR "Failed to register clocksource\n"); BUG(); @@ -341,6 +393,7 @@ static void __init tegra_init_timer(void) BUG(); } +#if 0 /* For T30.A01 use INT_TMR_SHARED instead of INT_TMR6. */ id = readl(chip_id); if (((id & 0xFF00) >> 8) == 0x30) { @@ -360,6 +413,7 @@ static void __init tegra_init_timer(void) } REGISTER_LP2_WAKE_IRQS(); +#endif clockevents_calc_mult_shift(&tegra_clockevent, 1000000, 5); tegra_clockevent.max_delta_ns = @@ -370,7 +424,10 @@ static void __init tegra_init_timer(void) tegra_clockevent.irq = tegra_timer_irq.irq; clockevents_register_device(&tegra_clockevent); + register_syscore_ops(&tegra_timer_syscore_ops); +#if 0 test_lp2_wake_timers(); +#endif return; } @@ -378,6 +435,7 @@ struct sys_timer tegra_timer = { .init = tegra_init_timer, }; +#if 0 #ifdef CONFIG_SMP #define hard_smp_processor_id() \ ({ \ @@ -418,16 +476,4 @@ unsigned long tegra_lp2_timer_remain(void) timer_base = lp2_wake_timers[cpu]; return timer_readl(timer_base + TIMER_PCR) & 0x1ffffffful; } - -static u32 usec_config; -void tegra_timer_suspend(void) -{ - tegra_sched_clock_suspend(); - usec_config = timer_readl(TIMERUS_USEC_CFG); -} - -void tegra_timer_resume(void) -{ - timer_writel(usec_config, TIMERUS_USEC_CFG); - tegra_sched_clock_resume(); -} +#endif |