diff options
Diffstat (limited to 'arch/arm/mach-tegra/hotplug.c')
-rw-r--r-- | arch/arm/mach-tegra/hotplug.c | 144 |
1 files changed, 54 insertions, 90 deletions
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c index f3294040d35..d44e457e718 100644 --- a/arch/arm/mach-tegra/hotplug.c +++ b/arch/arm/mach-tegra/hotplug.c | |||
@@ -1,119 +1,83 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-realview/hotplug.c | 2 | * arch/arm/mach-tegra/hotplug.c |
3 | * | 3 | * |
4 | * Copyright (C) 2002 ARM Ltd. | 4 | * Copyright (C) 2010-2011 NVIDIA Corporation |
5 | * All Rights Reserved | ||
6 | * | 5 | * |
7 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
10 | */ | 9 | */ |
11 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
12 | #include <linux/errno.h> | 11 | #include <linux/io.h> |
13 | #include <linux/smp.h> | 12 | #include <linux/smp.h> |
14 | 13 | ||
14 | #include <asm/cpu_pm.h> | ||
15 | #include <asm/cacheflush.h> | 15 | #include <asm/cacheflush.h> |
16 | 16 | ||
17 | static inline void cpu_enter_lowpower(void) | 17 | #include <mach/iomap.h> |
18 | { | ||
19 | unsigned int v; | ||
20 | 18 | ||
21 | flush_cache_all(); | 19 | #include "gic.h" |
22 | asm volatile( | 20 | #include "sleep.h" |
23 | " mcr p15, 0, %1, c7, c5, 0\n" | ||
24 | " mcr p15, 0, %1, c7, c10, 4\n" | ||
25 | /* | ||
26 | * Turn off coherency | ||
27 | */ | ||
28 | " mrc p15, 0, %0, c1, c0, 1\n" | ||
29 | " bic %0, %0, #0x20\n" | ||
30 | " mcr p15, 0, %0, c1, c0, 1\n" | ||
31 | " mrc p15, 0, %0, c1, c0, 0\n" | ||
32 | " bic %0, %0, %2\n" | ||
33 | " mcr p15, 0, %0, c1, c0, 0\n" | ||
34 | : "=&r" (v) | ||
35 | : "r" (0), "Ir" (CR_C) | ||
36 | : "cc"); | ||
37 | } | ||
38 | 21 | ||
39 | static inline void cpu_leave_lowpower(void) | 22 | #define CPU_CLOCK(cpu) (0x1<<(8+cpu)) |
40 | { | ||
41 | unsigned int v; | ||
42 | |||
43 | asm volatile( | ||
44 | "mrc p15, 0, %0, c1, c0, 0\n" | ||
45 | " orr %0, %0, %1\n" | ||
46 | " mcr p15, 0, %0, c1, c0, 0\n" | ||
47 | " mrc p15, 0, %0, c1, c0, 1\n" | ||
48 | " orr %0, %0, #0x20\n" | ||
49 | " mcr p15, 0, %0, c1, c0, 1\n" | ||
50 | : "=&r" (v) | ||
51 | : "Ir" (CR_C) | ||
52 | : "cc"); | ||
53 | } | ||
54 | 23 | ||
55 | static inline void platform_do_lowpower(unsigned int cpu, int *spurious) | 24 | #define CLK_RST_CONTROLLER_CLK_CPU_CMPLX \ |
56 | { | 25 | (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x4c) |
57 | /* | 26 | #define CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET \ |
58 | * there is no power-control hardware on this platform, so all | 27 | (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x340) |
59 | * we can do is put the core into WFI; this is safe as the calling | 28 | #define CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR \ |
60 | * code will have already disabled interrupts | 29 | (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x344) |
61 | */ | 30 | |
62 | for (;;) { | 31 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC |
63 | /* | 32 | /* For Tegra2 use the software-written value of the reset register for status.*/ |
64 | * here's the WFI | 33 | #define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET |
65 | */ | 34 | #else |
66 | asm(".word 0xe320f003\n" | 35 | #define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS \ |
67 | : | 36 | (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x470) |
68 | : | 37 | #endif |
69 | : "memory", "cc"); | ||
70 | |||
71 | /*if (pen_release == cpu) {*/ | ||
72 | /* | ||
73 | * OK, proper wakeup, we're done | ||
74 | */ | ||
75 | break; | ||
76 | /*}*/ | ||
77 | |||
78 | /* | ||
79 | * Getting here, means that we have come out of WFI without | ||
80 | * having been woken up - this shouldn't happen | ||
81 | * | ||
82 | * Just note it happening - when we're woken, we can report | ||
83 | * its occurrence. | ||
84 | */ | ||
85 | (*spurious)++; | ||
86 | } | ||
87 | } | ||
88 | 38 | ||
89 | int platform_cpu_kill(unsigned int cpu) | 39 | int platform_cpu_kill(unsigned int cpu) |
90 | { | 40 | { |
41 | unsigned int reg; | ||
42 | |||
43 | do { | ||
44 | reg = readl(CLK_RST_CONTROLLER_CPU_CMPLX_STATUS); | ||
45 | cpu_relax(); | ||
46 | } while (!(reg & (1<<cpu))); | ||
47 | |||
48 | reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX); | ||
49 | writel(reg | CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX); | ||
50 | |||
91 | return 1; | 51 | return 1; |
92 | } | 52 | } |
93 | 53 | ||
94 | /* | ||
95 | * platform-specific code to shutdown a CPU | ||
96 | * | ||
97 | * Called with IRQs disabled | ||
98 | */ | ||
99 | void platform_cpu_die(unsigned int cpu) | 54 | void platform_cpu_die(unsigned int cpu) |
100 | { | 55 | { |
101 | int spurious = 0; | 56 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC |
57 | /* Flush the L1 data cache. */ | ||
58 | flush_cache_all(); | ||
102 | 59 | ||
103 | /* | 60 | /* Place the current CPU in reset. */ |
104 | * we're ready for shutdown now, so do it | 61 | tegra2_hotplug_shutdown(); |
105 | */ | 62 | #else |
106 | cpu_enter_lowpower(); | 63 | /* Disable GIC CPU interface for this CPU. */ |
107 | platform_do_lowpower(cpu, &spurious); | 64 | tegra_gic_cpu_disable(); |
108 | 65 | ||
109 | /* | 66 | /* Tegra3 enters LPx states via WFI - do not propagate legacy IRQs |
110 | * bring this CPU back into the world of cache | 67 | to CPU core to avoid fall through WFI; then GIC output will be |
111 | * coherency, and then restore interrupts | 68 | enabled, however at this time - CPU is dying - no interrupt should |
112 | */ | 69 | have affinity to this CPU. */ |
113 | cpu_leave_lowpower(); | 70 | tegra_gic_pass_through_disable(); |
71 | |||
72 | /* Flush the L1 data cache. */ | ||
73 | flush_cache_all(); | ||
74 | |||
75 | /* Shut down the current CPU. */ | ||
76 | tegra3_hotplug_shutdown(); | ||
77 | #endif | ||
114 | 78 | ||
115 | if (spurious) | 79 | /* Should never return here. */ |
116 | pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); | 80 | BUG(); |
117 | } | 81 | } |
118 | 82 | ||
119 | int platform_cpu_disable(unsigned int cpu) | 83 | int platform_cpu_disable(unsigned int cpu) |