aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/timer-t2.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/timer-t2.c')
-rw-r--r--arch/arm/mach-tegra/timer-t2.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/timer-t2.c b/arch/arm/mach-tegra/timer-t2.c
new file mode 100644
index 00000000000..2d515abef16
--- /dev/null
+++ b/arch/arm/mach-tegra/timer-t2.c
@@ -0,0 +1,128 @@
1/*
2 * arch/arch/mach-tegra/timer.c
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Copyright (C) 2011 NVIDIA Corporation.
6 *
7 * Author:
8 * Colin Cross <ccross@google.com>
9 *
10 * This software is licensed under the terms of the GNU General Public
11 * License version 2, as published by the Free Software Foundation, and
12 * may be copied, distributed, and modified under those terms.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 */
20
21#include <linux/init.h>
22#include <linux/err.h>
23#include <linux/sched.h>
24#include <linux/time.h>
25#include <linux/interrupt.h>
26#include <linux/irq.h>
27#include <linux/clockchips.h>
28#include <linux/clocksource.h>
29#include <linux/clk.h>
30#include <linux/io.h>
31#include <linux/syscore_ops.h>
32
33#include <asm/mach/time.h>
34#include <asm/localtimer.h>
35#include <asm/sched_clock.h>
36
37#include <mach/iomap.h>
38#include <mach/irqs.h>
39
40#include "board.h"
41#include "clock.h"
42#include "timer.h"
43
44/*
45 * Timers usage:
46 * TMR1 - Free.
47 * TMR2 - used by AVP.
48 * TMR3 - used as general CPU timer.
49 * TMR4 - used for LP2 wakeup.
50*/
51
52#define TIMER1_OFFSET (TEGRA_TMR1_BASE-TEGRA_TMR1_BASE)
53#define TIMER2_OFFSET (TEGRA_TMR2_BASE-TEGRA_TMR1_BASE)
54#define TIMER3_OFFSET (TEGRA_TMR3_BASE-TEGRA_TMR1_BASE)
55#define TIMER4_OFFSET (TEGRA_TMR4_BASE-TEGRA_TMR1_BASE)
56
57#define timer_writel(value, reg) \
58 __raw_writel(value, (u32)timer_reg_base + (reg))
59#define timer_readl(reg) \
60 __raw_readl((u32)timer_reg_base + (reg))
61
62
63static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE);
64
65#ifdef CONFIG_PM_SLEEP
66static irqreturn_t tegra_lp2wake_interrupt(int irq, void *dev_id)
67{
68 timer_writel(1<<30, TIMER4_OFFSET + TIMER_PCR);
69 return IRQ_HANDLED;
70}
71
72static struct irqaction tegra_lp2wake_irq = {
73 .name = "timer_lp2wake",
74 .flags = IRQF_DISABLED,
75 .handler = tegra_lp2wake_interrupt,
76 .dev_id = NULL,
77 .irq = INT_TMR4,
78};
79
80void tegra2_lp2_set_trigger(unsigned long cycles)
81{
82 timer_writel(0, TIMER4_OFFSET + TIMER_PTV);
83 if (cycles) {
84 u32 reg = 0x80000000ul | min(0x1ffffffful, cycles);
85 timer_writel(reg, TIMER4_OFFSET + TIMER_PTV);
86 }
87}
88EXPORT_SYMBOL(tegra2_lp2_set_trigger);
89
90unsigned long tegra2_lp2_timer_remain(void)
91{
92 return timer_readl(TIMER4_OFFSET + TIMER_PCR) & 0x1ffffffful;
93}
94#endif
95
96void __init tegra2_init_timer(u32 *offset, int *irq)
97{
98 unsigned long rate = tegra_clk_measure_input_freq();
99 int ret;
100
101 switch (rate) {
102 case 12000000:
103 timer_writel(0x000b, TIMERUS_USEC_CFG);
104 break;
105 case 13000000:
106 timer_writel(0x000c, TIMERUS_USEC_CFG);
107 break;
108 case 19200000:
109 timer_writel(0x045f, TIMERUS_USEC_CFG);
110 break;
111 case 26000000:
112 timer_writel(0x0019, TIMERUS_USEC_CFG);
113 break;
114 default:
115 WARN(1, "Unknown clock rate");
116 }
117
118#ifdef CONFIG_PM_SLEEP
119 ret = setup_irq(tegra_lp2wake_irq.irq, &tegra_lp2wake_irq);
120 if (ret) {
121 pr_err("Failed to register LP2 timer IRQ: %d\n", ret);
122 BUG();
123 }
124#endif
125
126 *offset = TIMER3_OFFSET;
127 *irq = INT_TMR3;
128}