ARM: tegra: power: Fix LP2 timers suspend/resume
[linux-3.10.git] / arch / arm / mach-tegra / timer-t3.c
1 /*
2  * arch/arch/mach-tegra/timer-t3.c
3  *
4  * Copyright (c) 2011-2012, NVIDIA Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
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/smp.h>
32 #include <linux/syscore_ops.h>
33 #include <linux/cpu.h>
34 #include <linux/export.h>
35
36 #include <asm/mach/time.h>
37 #include <asm/localtimer.h>
38 #include <asm/sched_clock.h>
39
40 #include <mach/hardware.h>
41 #include <mach/iomap.h>
42 #include <mach/irqs.h>
43
44 #include "board.h"
45 #include "clock.h"
46 #include "cpuidle.h"
47 #include "timer.h"
48
49 #define TEST_LP2_WAKE_TIMERS    0
50
51 /*
52  * Timers usage:
53  * TMR1 - used as general CPU timer.
54  * TMR2 - used by AVP.
55  * TMR3 - used by CPU0 for LP2 wakeup.
56  * TMR4 - used by CPU1 for LP2 wakeup.
57  * TMR5 - used by CPU2 for LP2 wakeup.
58  * TMR6 - used by CPU3 for LP2 wakeup.
59  * TMR7 - Free.
60  * TMR8 - Free.
61  * TMR9 - Free.
62  * TMR10 - used as source for watchdog controller 0.
63 */
64
65 #define TIMER1_OFFSET (TEGRA_TMR1_BASE-TEGRA_TMR1_BASE)
66 #define TIMER2_OFFSET (TEGRA_TMR2_BASE-TEGRA_TMR1_BASE)
67 #define TIMER3_OFFSET (TEGRA_TMR3_BASE-TEGRA_TMR1_BASE)
68 #define TIMER4_OFFSET (TEGRA_TMR4_BASE-TEGRA_TMR1_BASE)
69 #define TIMER5_OFFSET (TEGRA_TMR5_BASE-TEGRA_TMR1_BASE)
70 #define TIMER6_OFFSET (TEGRA_TMR6_BASE-TEGRA_TMR1_BASE)
71
72 static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE);
73 static cpumask_t wake_timer_ready;
74 static cpumask_t wake_timer_canceled;
75
76 #define timer_writel(value, reg) \
77         __raw_writel(value, timer_reg_base + (reg))
78 #define timer_readl(reg) \
79         __raw_readl(timer_reg_base + (reg))
80
81
82 #ifdef CONFIG_PM_SLEEP
83 static u32 lp2_wake_timers[] = {
84         TIMER3_OFFSET,
85 #ifdef CONFIG_SMP
86         TIMER4_OFFSET,
87         TIMER5_OFFSET,
88         TIMER6_OFFSET,
89 #endif
90 };
91
92 static irqreturn_t tegra_lp2wake_interrupt(int irq, void *dev_id)
93 {
94         int cpu = (int)dev_id;
95         int base;
96
97         base = lp2_wake_timers[cpu];
98         timer_writel(1<<30, base + TIMER_PCR);
99         return IRQ_HANDLED;
100 }
101
102 #define LP2_TIMER_IRQ_ACTION(cpu, irqnum) {                     \
103         .name           = "tmr_lp2wake_cpu" __stringify(cpu),   \
104         .flags          = IRQF_DISABLED,                        \
105         .handler        = tegra_lp2wake_interrupt,              \
106         .dev_id         = (void*)cpu,                           \
107         .irq            = irqnum }
108
109 static struct irqaction tegra_lp2wake_irq[] = {
110         LP2_TIMER_IRQ_ACTION(0, INT_TMR3),
111 #ifdef CONFIG_SMP
112         LP2_TIMER_IRQ_ACTION(1, INT_TMR4),
113         LP2_TIMER_IRQ_ACTION(2, INT_TMR5),
114         LP2_TIMER_IRQ_ACTION(3, INT_TMR6),
115 #endif
116 };
117
118 #ifdef CONFIG_SMP
119 #define hard_smp_processor_id()                                         \
120         ({                                                              \
121                 unsigned int cpunum;                                    \
122                 __asm__("\n"                                            \
123                         "1:     mrc p15, 0, %0, c0, c0, 5\n"            \
124                         "       .pushsection \".alt.smp.init\", \"a\"\n"\
125                         "       .long   1b\n"                           \
126                         "       mov     %0, #0\n"                       \
127                         "       .popsection"                            \
128                         : "=r" (cpunum));                               \
129                 cpunum &= 0x0F;                                         \
130         })
131 #define cpu_number()    hard_smp_processor_id()
132 #else
133 #define cpu_number()    0
134 #endif
135
136 /*
137  * To sanity test LP2 timer interrupts for CPU 0-3, enable this flag and check
138  * /proc/interrupts for timer interrupts. CPUs 0-3 should have one interrupt
139  * counted against them for tmr_lp2wake_cpu<n>, where <n> is the CPU number.
140  */
141 #if TEST_LP2_WAKE_TIMERS
142 static void test_lp2_wake_timer(unsigned int cpu)
143 {
144         unsigned long cycles = 50000;
145         unsigned int base = lp2_wake_timers[cpu];
146         static bool tested[4] = {false, false, false, false};
147
148         /* Don't repeat the test process on hotplug restart. */
149         if (!tested[cpu]) {
150                 timer_writel(0, base + TIMER_PTV);
151                 if (cycles) {
152                         u32 reg = 0x80000000ul | min(0x1ffffffful, cycles);
153                         timer_writel(reg, base + TIMER_PTV);
154                         tested[cpu] = true;
155                 }
156         }
157 }
158 #else
159 static inline void test_lp2_wake_timer(unsigned int cpu) {}
160 #endif
161
162 static int tegra3_resume_wake_timer(unsigned int cpu)
163 {
164 #ifdef CONFIG_SMP
165         int ret = irq_set_affinity(tegra_lp2wake_irq[cpu].irq, cpumask_of(cpu));
166         if (ret) {
167                 pr_err("Failed to set affinity for LP2 timer IRQ to "
168                         "CPU %d: irq=%d, ret=%d\n", cpu,
169                         tegra_lp2wake_irq[cpu].irq, ret);
170                 return ret;
171         }
172 #endif
173         cpumask_set_cpu(cpu, &wake_timer_ready);
174         return 0;
175 }
176
177 static void tegra3_register_wake_timer(unsigned int cpu)
178 {
179         int ret;
180
181         ret = setup_irq(tegra_lp2wake_irq[cpu].irq, &tegra_lp2wake_irq[cpu]);
182         if (ret) {
183                 pr_err("Failed to register LP2 timer IRQ for CPU %d: "
184                         "irq=%d, ret=%d\n", cpu,
185                         tegra_lp2wake_irq[cpu].irq, ret);
186                 goto fail;
187         }
188
189         ret = tegra3_resume_wake_timer(cpu);
190         if (ret)
191                 goto fail;
192
193         test_lp2_wake_timer(cpu);
194         return;
195 fail:
196         tegra_lp2_in_idle(false);
197 }
198
199 #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_HOTPLUG_CPU)
200 static void tegra3_suspend_wake_timer(unsigned int cpu)
201 {
202         cpumask_clear_cpu(cpu, &wake_timer_ready);
203 #ifdef CONFIG_SMP
204         /* Reassign the affinity of the wake IRQ to CPU 0. */
205         (void)irq_set_affinity(tegra_lp2wake_irq[cpu].irq, cpumask_of(0));
206 #endif
207 }
208
209 static void tegra3_unregister_wake_timer(unsigned int cpu)
210 {
211         tegra3_suspend_wake_timer(cpu);
212
213         /* Dispose of this IRQ. */
214         remove_irq(tegra_lp2wake_irq[cpu].irq, &tegra_lp2wake_irq[cpu]);
215 }
216 #endif
217
218 void tegra3_lp2_set_trigger(unsigned long cycles)
219 {
220         int cpu = cpu_number();
221         int base;
222
223         base = lp2_wake_timers[cpu];
224         timer_writel(0, base + TIMER_PTV);
225         if (cycles) {
226                 u32 reg = 0x80000000ul | min(0x1ffffffful, cycles);
227                 timer_writel(reg, base + TIMER_PTV);
228         }
229 }
230 EXPORT_SYMBOL(tegra3_lp2_set_trigger);
231
232 unsigned long tegra3_lp2_timer_remain(void)
233 {
234         int cpu = cpu_number();
235
236         if (cpumask_test_and_clear_cpu(cpu, &wake_timer_canceled))
237                 return -ETIME;
238
239         return timer_readl(lp2_wake_timers[cpu] + TIMER_PCR) & 0x1ffffffful;
240 }
241
242 int tegra3_is_lp2_timer_ready(unsigned int cpu)
243 {
244         return cpumask_test_cpu(cpu, &wake_timer_ready);
245 }
246
247 void tegra3_lp2_timer_cancel_secondary(void)
248 {
249         int cpu;
250         int base;
251
252         for (cpu = 1; cpu < ARRAY_SIZE(lp2_wake_timers); cpu++) {
253                 base = lp2_wake_timers[cpu];
254                 cpumask_set_cpu(cpu, &wake_timer_canceled);
255                 timer_writel(0, base + TIMER_PTV);
256                 timer_writel(1<<30, base + TIMER_PCR);
257         }
258 }
259 #endif
260
261 void __init tegra3_init_timer(u32 *offset, int *irq, unsigned long rate)
262 {
263         switch (rate) {
264         case 12000000:
265                 timer_writel(0x000b, TIMERUS_USEC_CFG);
266                 break;
267         case 13000000:
268                 timer_writel(0x000c, TIMERUS_USEC_CFG);
269                 break;
270         case 19200000:
271                 timer_writel(0x045f, TIMERUS_USEC_CFG);
272                 break;
273         case 26000000:
274                 timer_writel(0x0019, TIMERUS_USEC_CFG);
275                 break;
276         case 16800000:
277                 timer_writel(0x0453, TIMERUS_USEC_CFG);
278                 break;
279         case 38400000:
280                 timer_writel(0x04BF, TIMERUS_USEC_CFG);
281                 break;
282         case 48000000:
283                 timer_writel(0x002F, TIMERUS_USEC_CFG);
284                 break;
285         default:
286                 WARN(1, "Unknown clock rate");
287         }
288
289 #ifdef CONFIG_PM_SLEEP
290 #ifdef CONFIG_SMP
291         /* For T30.A01 use INT_TMR_SHARED instead of INT_TMR6 for CPU3. */
292         if ((tegra_chip_id == TEGRA30) &&
293                 (tegra_revision == TEGRA_REVISION_A01))
294                         tegra_lp2wake_irq[3].irq = INT_TMR_SHARED;
295 #endif
296
297         tegra3_register_wake_timer(0);
298 #endif
299
300         *offset = TIMER1_OFFSET;
301         *irq = INT_TMR1;
302 }
303
304 #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_HOTPLUG_CPU)
305 static int hotplug_notify(struct notifier_block *self,
306                                       unsigned long action, void *cpu)
307 {
308         switch (action) {
309         case CPU_ONLINE:
310                 tegra3_register_wake_timer((unsigned int)cpu);
311                 break;
312         case CPU_ONLINE_FROZEN:
313                 tegra3_resume_wake_timer((unsigned int)cpu);
314                 break;
315         case CPU_DOWN_PREPARE:
316                 tegra3_unregister_wake_timer((unsigned int)cpu);
317                 break;
318         case CPU_DOWN_PREPARE_FROZEN:
319                 tegra3_suspend_wake_timer((unsigned int)cpu);
320                 break;
321         default:
322                 break;
323         }
324
325         return NOTIFY_OK;
326 }
327
328 static struct notifier_block __cpuinitdata hotplug_notifier_block = {
329         .notifier_call = hotplug_notify,
330 };
331
332 static int __init hotplug_cpu_register(void)
333 {
334         return register_cpu_notifier(&hotplug_notifier_block);
335 }
336 early_initcall(hotplug_cpu_register);
337 #endif