b21016186d36f6048d041a072ae34a3418b7ac49
[linux-3.10.git] / arch / arm / mach-tegra / timer-t2.c
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/time.h>
24 #include <linux/interrupt.h>
25 #include <linux/irq.h>
26 #include <linux/clockchips.h>
27 #include <linux/clocksource.h>
28 #include <linux/clk.h>
29 #include <linux/io.h>
30 #include <linux/syscore_ops.h>
31 #include <linux/export.h>
32
33 #include <asm/mach/time.h>
34 #include <asm/smp_twd.h>
35 #include <asm/sched_clock.h>
36
37 #include <mach/irqs.h>
38
39 #include "board.h"
40 #include "clock.h"
41 #include "iomap.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, timer_reg_base + (reg))
59 #define timer_readl(reg) \
60         __raw_readl(timer_reg_base + (reg))
61
62 static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE);
63
64 #ifdef CONFIG_PM_SLEEP
65 static irqreturn_t tegra_lp2wake_interrupt(int irq, void *dev_id)
66 {
67         timer_writel(1<<30, TIMER4_OFFSET + TIMER_PCR);
68         return IRQ_HANDLED;
69 }
70
71 static struct irqaction tegra_lp2wake_irq = {
72         .name           = "timer_lp2wake",
73         .flags          = IRQF_DISABLED,
74         .handler        = tegra_lp2wake_interrupt,
75         .dev_id         = NULL,
76         .irq            = INT_TMR4,
77 };
78
79 void tegra2_lp2_set_trigger(unsigned long cycles)
80 {
81         timer_writel(0, TIMER4_OFFSET + TIMER_PTV);
82         if (cycles) {
83                 u32 reg = 0x80000000ul | min(0x1ffffffful, cycles);
84                 timer_writel(reg, TIMER4_OFFSET + TIMER_PTV);
85         }
86 }
87 EXPORT_SYMBOL(tegra2_lp2_set_trigger);
88
89 unsigned long tegra2_lp2_timer_remain(void)
90 {
91         return timer_readl(TIMER4_OFFSET + TIMER_PCR) & 0x1ffffffful;
92 }
93 #endif
94
95 void __init tegra2_init_timer(u32 *offset, int *irq, unsigned long rate)
96 {
97         int ret;
98
99         switch (rate) {
100         case 12000000:
101                 timer_writel(0x000b, TIMERUS_USEC_CFG);
102                 break;
103         case 13000000:
104                 timer_writel(0x000c, TIMERUS_USEC_CFG);
105                 break;
106         case 19200000:
107                 timer_writel(0x045f, TIMERUS_USEC_CFG);
108                 break;
109         case 26000000:
110                 timer_writel(0x0019, TIMERUS_USEC_CFG);
111                 break;
112         default:
113                 WARN(1, "Unknown clock rate");
114         }
115
116 #ifdef CONFIG_PM_SLEEP
117         ret = setup_irq(tegra_lp2wake_irq.irq, &tegra_lp2wake_irq);
118         if (ret) {
119                 pr_err("Failed to register LP2 timer IRQ: %d\n", ret);
120                 BUG();
121         }
122 #endif
123
124         *offset = TIMER3_OFFSET;
125         *irq = INT_TMR3;
126 }