ARM: tegra12: set CPU rate to 2.2GHz for sku 0x87
[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/localtimer.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
63 static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE);
64
65 #ifdef CONFIG_PM_SLEEP
66 static 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
72 static 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
80 void 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 }
88 EXPORT_SYMBOL(tegra2_lp2_set_trigger);
89
90 unsigned long tegra2_lp2_timer_remain(void)
91 {
92         return timer_readl(TIMER4_OFFSET + TIMER_PCR) & 0x1ffffffful;
93 }
94 #endif
95
96 void __init tegra20_init_timer(void)
97 {
98         int ret;
99
100 #ifdef CONFIG_PM_SLEEP
101         ret = setup_irq(tegra_lp2wake_irq.irq, &tegra_lp2wake_irq);
102         if (ret) {
103                 pr_err("Failed to register LP2 timer IRQ: %d\n", ret);
104                 BUG();
105         }
106 #endif
107 }