aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/hotplug.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/hotplug.c')
-rw-r--r--arch/arm/mach-tegra/hotplug.c144
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
17static 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
39static 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
55static 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
89int platform_cpu_kill(unsigned int cpu) 39int 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 */
99void platform_cpu_die(unsigned int cpu) 54void 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
119int platform_cpu_disable(unsigned int cpu) 83int platform_cpu_disable(unsigned int cpu)