ARM: tegra: power: Overlap Tegra3 cpu off delay
[linux-3.10.git] / arch / arm / mach-tegra / pm-t3.c
1 /*
2  * arch/arm/mach-tegra/pm-t3.c
3  *
4  * Tegra3 SOC-specific power and cluster management
5  *
6  * Copyright (c) 2009-2011, NVIDIA Corporation.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17  */
18
19 #include <linux/kernel.h>
20 #include <linux/init.h>
21 #include <linux/io.h>
22 #include <linux/smp.h>
23 #include <linux/interrupt.h>
24 #include <linux/clk.h>
25 #include <linux/cpu_pm.h>
26 #include <linux/delay.h>
27
28 #include <mach/gpio.h>
29 #include <mach/irqs.h>
30
31 #include <asm/hardware/gic.h>
32
33 #include "clock.h"
34 #include "cpuidle.h"
35 #include "flowctrl.h"
36 #include "gpio-names.h"
37 #include "iomap.h"
38 #include "pm.h"
39 #include "sleep.h"
40 #include "tegra3_emc.h"
41
42 #define CAR_CCLK_BURST_POLICY \
43         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x20)
44
45 #define CAR_SUPER_CCLK_DIVIDER \
46         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x24)
47
48 #define CAR_CCLKG_BURST_POLICY \
49         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x368)
50
51 #define CAR_SUPER_CCLKG_DIVIDER \
52         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x36C)
53
54 #define CAR_CCLKLP_BURST_POLICY \
55         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x370)
56 #define PLLX_DIV2_BYPASS_LP     (1<<16)
57
58 #define CAR_SUPER_CCLKLP_DIVIDER \
59         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x374)
60
61 #define CAR_BOND_OUT_V \
62         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x390)
63 #define CAR_BOND_OUT_V_CPU_G    (1<<0)
64 #define CAR_BOND_OUT_V_CPU_LP   (1<<1)
65
66 #define CAR_CLK_ENB_V_SET \
67         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x440)
68 #define CAR_CLK_ENB_V_CPU_G     (1<<0)
69 #define CAR_CLK_ENB_V_CPU_LP    (1<<1)
70
71 #define CAR_RST_CPUG_CMPLX_SET \
72         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x450)
73
74 #define CAR_RST_CPUG_CMPLX_CLR \
75         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x454)
76
77 #define CAR_RST_CPULP_CMPLX_SET \
78         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x458)
79
80 #define CAR_RST_CPULP_CMPLX_CLR \
81         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x45C)
82
83 #define CAR_CLK_CPUG_CMPLX_SET \
84         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x460)
85
86 #define CAR_CLK_CPUG_CMPLX_CLR \
87         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x464)
88
89 #define CAR_CLK_CPULP_CMPLX_SET \
90         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x468)
91
92 #define CAR_CLK_CPULP_CMPLX_CLR \
93         (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x46C)
94
95 #define CPU_CLOCK(cpu)  (0x1<<(8+cpu))
96 #define CPU_RESET(cpu)  (0x1111ul<<(cpu))
97
98 #ifdef CONFIG_PM_SLEEP
99 static int cluster_switch_prolog_clock(unsigned int flags)
100 {
101         u32 reg;
102         u32 CclkBurstPolicy;
103         u32 SuperCclkDivier;
104
105         /* Read the bond out register containing the G and LP CPUs. */
106         reg = readl(CAR_BOND_OUT_V);
107
108         /* Sync G-PLLX divider bypass with LP (no effect on G, just to prevent
109            LP settings overwrite by save/restore code */
110         CclkBurstPolicy = ~PLLX_DIV2_BYPASS_LP & readl(CAR_CCLKG_BURST_POLICY);
111         CclkBurstPolicy |= PLLX_DIV2_BYPASS_LP & readl(CAR_CCLKLP_BURST_POLICY);
112         writel(CclkBurstPolicy, CAR_CCLKG_BURST_POLICY);
113
114         /* Switching to G? */
115         if (flags & TEGRA_POWER_CLUSTER_G) {
116                 /* Do the G CPUs exist? */
117                 if (reg & CAR_BOND_OUT_V_CPU_G)
118                         return -ENXIO;
119
120                 /* Keep G CPU clock policy set by upper laayer, with the
121                    exception of the transition via LP1 */
122                 if (flags & TEGRA_POWER_SDRAM_SELFREFRESH) {
123                         /* In LP1 power mode come up on CLKM (oscillator) */
124                         CclkBurstPolicy = readl(CAR_CCLKG_BURST_POLICY);
125                         CclkBurstPolicy |= ~0xF;
126                         SuperCclkDivier = 0;
127
128                         writel(CclkBurstPolicy, CAR_CCLKG_BURST_POLICY);
129                         writel(SuperCclkDivier, CAR_SUPER_CCLKG_DIVIDER);
130                 }
131
132                 /* Hold G CPUs 1-3 in reset after the switch */
133                 reg = CPU_RESET(1) | CPU_RESET(2) | CPU_RESET(3);
134                 writel(reg, CAR_RST_CPUG_CMPLX_SET);
135
136                 /* Take G CPU 0 out of reset after the switch */
137                 reg = CPU_RESET(0);
138                 writel(reg, CAR_RST_CPUG_CMPLX_CLR);
139
140                 /* Disable the clocks on G CPUs 1-3 after the switch */
141                 reg = CPU_CLOCK(1) | CPU_CLOCK(2) | CPU_CLOCK(3);
142                 writel(reg, CAR_CLK_CPUG_CMPLX_SET);
143
144                 /* Enable the clock on G CPU 0 after the switch */
145                 reg = CPU_CLOCK(0);
146                 writel(reg, CAR_CLK_CPUG_CMPLX_CLR);
147
148                 /* Enable the G CPU complex clock after the switch */
149                 reg = CAR_CLK_ENB_V_CPU_G;
150                 writel(reg, CAR_CLK_ENB_V_SET);
151         }
152         /* Switching to LP? */
153         else if (flags & TEGRA_POWER_CLUSTER_LP) {
154                 /* Does the LP CPU exist? */
155                 if (reg & CAR_BOND_OUT_V_CPU_LP)
156                         return -ENXIO;
157
158                 /* Keep LP CPU clock policy set by upper layer, with the
159                    exception of the transition via LP1 */
160                 if (flags & TEGRA_POWER_SDRAM_SELFREFRESH) {
161                         /* In LP1 power mode come up on CLKM (oscillator) */
162                         CclkBurstPolicy = readl(CAR_CCLKLP_BURST_POLICY);
163                         CclkBurstPolicy |= ~0xF;
164                         SuperCclkDivier = 0;
165
166                         writel(CclkBurstPolicy, CAR_CCLKLP_BURST_POLICY);
167                         writel(SuperCclkDivier, CAR_SUPER_CCLKLP_DIVIDER);
168                 }
169
170                 /* Take the LP CPU ut of reset after the switch */
171                 reg = CPU_RESET(0);
172                 writel(reg, CAR_RST_CPULP_CMPLX_CLR);
173
174                 /* Enable the clock on the LP CPU after the switch */
175                 reg = CPU_CLOCK(0);
176                 writel(reg, CAR_CLK_CPULP_CMPLX_CLR);
177
178                 /* Enable the LP CPU complex clock after the switch */
179                 reg = CAR_CLK_ENB_V_CPU_LP;
180                 writel(reg, CAR_CLK_ENB_V_SET);
181         }
182
183         return 0;
184 }
185
186 void tegra_cluster_switch_prolog(unsigned int flags)
187 {
188         unsigned int target_cluster = flags & TEGRA_POWER_CLUSTER_MASK;
189         unsigned int current_cluster = is_lp_cluster()
190                                         ? TEGRA_POWER_CLUSTER_LP
191                                         : TEGRA_POWER_CLUSTER_G;
192         u32 reg;
193
194         /* Read the flow controler CSR register and clear the CPU switch
195            and immediate flags. If an actual CPU switch is to be performed,
196            re-write the CSR register with the desired values. */
197         reg = flowctrl_read_cpu_csr(0);
198         reg &= ~(FLOW_CTRL_CSR_IMMEDIATE_WAKE |
199                  FLOW_CTRL_CSR_SWITCH_CLUSTER);
200
201         /* Program flow controller for immediate wake if requested */
202         if (flags & TEGRA_POWER_CLUSTER_IMMEDIATE)
203                 reg |= FLOW_CTRL_CSR_IMMEDIATE_WAKE;
204
205         /* Do nothing if no switch actions requested */
206         if (!target_cluster)
207                 goto done;
208
209         if ((current_cluster != target_cluster) ||
210                 (flags & TEGRA_POWER_CLUSTER_FORCE)) {
211                 if (current_cluster != target_cluster) {
212                         // Set up the clocks for the target CPU.
213                         if (cluster_switch_prolog_clock(flags)) {
214                                 /* The target CPU does not exist */
215                                 goto done;
216                         }
217
218                         /* Set up the flow controller to switch CPUs. */
219                         reg |= FLOW_CTRL_CSR_SWITCH_CLUSTER;
220                 }
221         }
222
223 done:
224         flowctrl_write_cpu_csr(0, reg);
225 }
226
227 static void cluster_switch_epilog_gic(void)
228 {
229         unsigned int max_irq, i;
230         void __iomem *gic_base = IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE);
231
232         /* Nothing to do if currently running on the LP CPU. */
233         if (is_lp_cluster())
234                 return;
235
236         /* Reprogram the interrupt affinity because the on the LP CPU,
237            the interrupt distributor affinity regsiters are stubbed out
238            by ARM (reads as zero, writes ignored). So when the LP CPU
239            context save code runs, the affinity registers will read
240            as all zero. This causes all interrupts to be effectively
241            disabled when back on the G CPU because they aren't routable
242            to any CPU. See bug 667720 for details. */
243
244         max_irq = readl(gic_base + GIC_DIST_CTR) & 0x1f;
245         max_irq = (max_irq + 1) * 32;
246
247         for (i = 32; i < max_irq; i += 4)
248                 writel(0x01010101, gic_base + GIC_DIST_TARGET + i * 4 / 4);
249 }
250
251 void tegra_cluster_switch_epilog(unsigned int flags)
252 {
253         u32 reg;
254
255         /* Make sure the switch and immediate flags are cleared in
256            the flow controller to prevent undesirable side-effects
257            for future users of the flow controller. */
258         reg = flowctrl_read_cpu_csr(0);
259         reg &= ~(FLOW_CTRL_CSR_IMMEDIATE_WAKE |
260                  FLOW_CTRL_CSR_SWITCH_CLUSTER);
261         flowctrl_write_cpu_csr(0, reg);
262
263         /* Perform post-switch clean-up of the interrupt distributor */
264         cluster_switch_epilog_gic();
265
266         #if DEBUG_CLUSTER_SWITCH
267         {
268                 /* FIXME: clock functions below are taking mutex */
269                 struct clk *c = tegra_get_clock_by_name(
270                         is_lp_cluster() ? "cpu_lp" : "cpu_g");
271                 DEBUG_CLUSTER(("%s: %s freq %lu\r\n", __func__,
272                         is_lp_cluster() ? "LP" : "G", clk_get_rate(c)));
273         }
274         #endif
275 }
276
277 int tegra_cluster_control(unsigned int us, unsigned int flags)
278 {
279 #ifdef CONFIG_PM_SLEEP
280         static ktime_t last_g2lp;
281
282         unsigned int target_cluster = flags & TEGRA_POWER_CLUSTER_MASK;
283         unsigned int current_cluster = is_lp_cluster()
284                                         ? TEGRA_POWER_CLUSTER_LP
285                                         : TEGRA_POWER_CLUSTER_G;
286         unsigned long irq_flags;
287
288         if ((target_cluster == TEGRA_POWER_CLUSTER_MASK) || !target_cluster)
289                 return -EINVAL;
290
291         if (num_online_cpus() > 1)
292                 return -EBUSY;
293
294         if ((current_cluster == target_cluster)
295         && !(flags & TEGRA_POWER_CLUSTER_FORCE))
296                 return -EEXIST;
297
298         if (target_cluster == TEGRA_POWER_CLUSTER_G)
299                 if (!is_g_cluster_present())
300                         return -EPERM;
301
302         if (flags & TEGRA_POWER_CLUSTER_IMMEDIATE)
303                 us = 0;
304
305         if (current_cluster != target_cluster) {
306                 if (target_cluster == TEGRA_POWER_CLUSTER_G) {
307                         s64 t = ktime_to_us(ktime_sub(ktime_get(), last_g2lp));
308                         s64 t_off = tegra_cpu_power_off_time();
309                         if (t_off > t)
310                                 udelay((unsigned int)(t_off - t));
311                 }
312                 else
313                         last_g2lp = ktime_get();
314         }
315
316         DEBUG_CLUSTER(("%s(LP%d): %s->%s %s %s %d\r\n", __func__,
317                 (flags & TEGRA_POWER_SDRAM_SELFREFRESH) ? 1 : 2,
318                 is_lp_cluster() ? "LP" : "G",
319                 (target_cluster == TEGRA_POWER_CLUSTER_G) ? "G" : "LP",
320                 (flags & TEGRA_POWER_CLUSTER_IMMEDIATE) ? "immediate" : "",
321                 (flags & TEGRA_POWER_CLUSTER_FORCE) ? "force" : "",
322                 us));
323
324         local_irq_save(irq_flags);
325         if (flags & TEGRA_POWER_SDRAM_SELFREFRESH) {
326                 if (us)
327                         tegra_lp2_set_trigger(us);
328
329                 tegra_suspend_dram(TEGRA_SUSPEND_LP1);
330
331                 if (us)
332                         tegra_lp2_set_trigger(0);
333         } else {
334                 tegra_set_cpu_in_lp2(0);
335                 cpu_pm_enter();
336                 tegra_idle_lp2_last(0, flags);
337                 cpu_pm_exit();
338                 tegra_clear_cpu_in_lp2(0);
339         }
340         local_irq_restore(irq_flags);
341
342         DEBUG_CLUSTER(("%s: %s\r\n", __func__, is_lp_cluster() ? "LP" : "G"));
343
344         return 0;
345 #else
346         return -ENODEV;
347 #endif
348 }
349
350 static u32 mc_reserved_rsv;
351 static u32 mc_emem_arb_override;
352
353 void tegra_lp0_suspend_mc(void)
354 {
355         void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE);
356         mc_reserved_rsv = readl(mc + MC_RESERVED_RSV);
357         mc_emem_arb_override = readl(mc + MC_EMEM_ARB_OVERRIDE);
358 }
359
360 void tegra_lp0_resume_mc(void)
361 {
362         void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE);
363         writel(mc_reserved_rsv, mc + MC_RESERVED_RSV);
364         writel(mc_emem_arb_override, mc + MC_EMEM_ARB_OVERRIDE);
365 }
366
367 void tegra_lp0_cpu_mode(bool enter)
368 {
369         static bool entered_on_g = false;
370         unsigned int flags;
371
372         if (enter)
373                 entered_on_g = !is_lp_cluster();
374
375         if (entered_on_g) {
376                 flags = enter ? TEGRA_POWER_CLUSTER_LP : TEGRA_POWER_CLUSTER_G;
377                 flags |= TEGRA_POWER_CLUSTER_IMMEDIATE;
378                 tegra_cluster_control(0, flags);
379         }
380 }
381 #endif