diff options
Diffstat (limited to 'arch/arm/mach-tegra/platsmp.c')
-rw-r--r-- | arch/arm/mach-tegra/platsmp.c | 119 |
1 files changed, 54 insertions, 65 deletions
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index 2c6b3d55213b..516aab28fe34 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c | |||
@@ -26,22 +26,16 @@ | |||
26 | #include <asm/smp_scu.h> | 26 | #include <asm/smp_scu.h> |
27 | #include <asm/smp_plat.h> | 27 | #include <asm/smp_plat.h> |
28 | 28 | ||
29 | #include <mach/powergate.h> | ||
30 | |||
31 | #include "fuse.h" | 29 | #include "fuse.h" |
32 | #include "flowctrl.h" | 30 | #include "flowctrl.h" |
33 | #include "reset.h" | 31 | #include "reset.h" |
32 | #include "pmc.h" | ||
34 | 33 | ||
35 | #include "common.h" | 34 | #include "common.h" |
36 | #include "iomap.h" | 35 | #include "iomap.h" |
37 | 36 | ||
38 | extern void tegra_secondary_startup(void); | ||
39 | |||
40 | static cpumask_t tegra_cpu_init_mask; | 37 | static cpumask_t tegra_cpu_init_mask; |
41 | 38 | ||
42 | #define EVP_CPU_RESET_VECTOR \ | ||
43 | (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100) | ||
44 | |||
45 | static void __cpuinit tegra_secondary_init(unsigned int cpu) | 39 | static void __cpuinit tegra_secondary_init(unsigned int cpu) |
46 | { | 40 | { |
47 | /* | 41 | /* |
@@ -54,25 +48,43 @@ static void __cpuinit tegra_secondary_init(unsigned int cpu) | |||
54 | cpumask_set_cpu(cpu, &tegra_cpu_init_mask); | 48 | cpumask_set_cpu(cpu, &tegra_cpu_init_mask); |
55 | } | 49 | } |
56 | 50 | ||
57 | static int tegra20_power_up_cpu(unsigned int cpu) | 51 | |
52 | static int tegra20_boot_secondary(unsigned int cpu, struct task_struct *idle) | ||
58 | { | 53 | { |
59 | /* Enable the CPU clock. */ | 54 | cpu = cpu_logical_map(cpu); |
60 | tegra_enable_cpu_clock(cpu); | 55 | |
56 | /* | ||
57 | * Force the CPU into reset. The CPU must remain in reset when | ||
58 | * the flow controller state is cleared (which will cause the | ||
59 | * flow controller to stop driving reset if the CPU has been | ||
60 | * power-gated via the flow controller). This will have no | ||
61 | * effect on first boot of the CPU since it should already be | ||
62 | * in reset. | ||
63 | */ | ||
64 | tegra_put_cpu_in_reset(cpu); | ||
61 | 65 | ||
62 | /* Clear flow controller CSR. */ | 66 | /* |
63 | flowctrl_write_cpu_csr(cpu, 0); | 67 | * Unhalt the CPU. If the flow controller was used to |
68 | * power-gate the CPU this will cause the flow controller to | ||
69 | * stop driving reset. The CPU will remain in reset because the | ||
70 | * clock and reset block is now driving reset. | ||
71 | */ | ||
72 | flowctrl_write_cpu_halt(cpu, 0); | ||
64 | 73 | ||
74 | tegra_enable_cpu_clock(cpu); | ||
75 | flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */ | ||
76 | tegra_cpu_out_of_reset(cpu); | ||
65 | return 0; | 77 | return 0; |
66 | } | 78 | } |
67 | 79 | ||
68 | static int tegra30_power_up_cpu(unsigned int cpu) | 80 | static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle) |
69 | { | 81 | { |
70 | int ret, pwrgateid; | 82 | int ret; |
71 | unsigned long timeout; | 83 | unsigned long timeout; |
72 | 84 | ||
73 | pwrgateid = tegra_cpu_powergate_id(cpu); | 85 | cpu = cpu_logical_map(cpu); |
74 | if (pwrgateid < 0) | 86 | tegra_put_cpu_in_reset(cpu); |
75 | return pwrgateid; | 87 | flowctrl_write_cpu_halt(cpu, 0); |
76 | 88 | ||
77 | /* | 89 | /* |
78 | * The power up sequence of cold boot CPU and warm boot CPU | 90 | * The power up sequence of cold boot CPU and warm boot CPU |
@@ -85,13 +97,13 @@ static int tegra30_power_up_cpu(unsigned int cpu) | |||
85 | * the IO clamps. | 97 | * the IO clamps. |
86 | * For cold boot CPU, do not wait. After the cold boot CPU be | 98 | * For cold boot CPU, do not wait. After the cold boot CPU be |
87 | * booted, it will run to tegra_secondary_init() and set | 99 | * booted, it will run to tegra_secondary_init() and set |
88 | * tegra_cpu_init_mask which influences what tegra30_power_up_cpu() | 100 | * tegra_cpu_init_mask which influences what tegra30_boot_secondary() |
89 | * next time around. | 101 | * next time around. |
90 | */ | 102 | */ |
91 | if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) { | 103 | if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) { |
92 | timeout = jiffies + msecs_to_jiffies(50); | 104 | timeout = jiffies + msecs_to_jiffies(50); |
93 | do { | 105 | do { |
94 | if (!tegra_powergate_is_powered(pwrgateid)) | 106 | if (tegra_pmc_cpu_is_powered(cpu)) |
95 | goto remove_clamps; | 107 | goto remove_clamps; |
96 | udelay(10); | 108 | udelay(10); |
97 | } while (time_before(jiffies, timeout)); | 109 | } while (time_before(jiffies, timeout)); |
@@ -103,14 +115,14 @@ static int tegra30_power_up_cpu(unsigned int cpu) | |||
103 | * be un-gated by un-toggling the power gate register | 115 | * be un-gated by un-toggling the power gate register |
104 | * manually. | 116 | * manually. |
105 | */ | 117 | */ |
106 | if (!tegra_powergate_is_powered(pwrgateid)) { | 118 | if (!tegra_pmc_cpu_is_powered(cpu)) { |
107 | ret = tegra_powergate_power_on(pwrgateid); | 119 | ret = tegra_pmc_cpu_power_on(cpu); |
108 | if (ret) | 120 | if (ret) |
109 | return ret; | 121 | return ret; |
110 | 122 | ||
111 | /* Wait for the power to come up. */ | 123 | /* Wait for the power to come up. */ |
112 | timeout = jiffies + msecs_to_jiffies(100); | 124 | timeout = jiffies + msecs_to_jiffies(100); |
113 | while (tegra_powergate_is_powered(pwrgateid)) { | 125 | while (tegra_pmc_cpu_is_powered(cpu)) { |
114 | if (time_after(jiffies, timeout)) | 126 | if (time_after(jiffies, timeout)) |
115 | return -ETIMEDOUT; | 127 | return -ETIMEDOUT; |
116 | udelay(10); | 128 | udelay(10); |
@@ -123,57 +135,34 @@ remove_clamps: | |||
123 | udelay(10); | 135 | udelay(10); |
124 | 136 | ||
125 | /* Remove I/O clamps. */ | 137 | /* Remove I/O clamps. */ |
126 | ret = tegra_powergate_remove_clamping(pwrgateid); | 138 | ret = tegra_pmc_cpu_remove_clamping(cpu); |
127 | udelay(10); | 139 | if (ret) |
140 | return ret; | ||
128 | 141 | ||
129 | /* Clear flow controller CSR. */ | 142 | udelay(10); |
130 | flowctrl_write_cpu_csr(cpu, 0); | ||
131 | 143 | ||
144 | flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */ | ||
145 | tegra_cpu_out_of_reset(cpu); | ||
132 | return 0; | 146 | return 0; |
133 | } | 147 | } |
134 | 148 | ||
135 | static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct *idle) | 149 | static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle) |
136 | { | 150 | { |
137 | int status; | ||
138 | |||
139 | cpu = cpu_logical_map(cpu); | 151 | cpu = cpu_logical_map(cpu); |
152 | return tegra_pmc_cpu_power_on(cpu); | ||
153 | } | ||
140 | 154 | ||
141 | /* | 155 | static int __cpuinit tegra_boot_secondary(unsigned int cpu, |
142 | * Force the CPU into reset. The CPU must remain in reset when the | 156 | struct task_struct *idle) |
143 | * flow controller state is cleared (which will cause the flow | 157 | { |
144 | * controller to stop driving reset if the CPU has been power-gated | 158 | if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20) |
145 | * via the flow controller). This will have no effect on first boot | 159 | return tegra20_boot_secondary(cpu, idle); |
146 | * of the CPU since it should already be in reset. | 160 | if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30) |
147 | */ | 161 | return tegra30_boot_secondary(cpu, idle); |
148 | tegra_put_cpu_in_reset(cpu); | 162 | if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114) |
149 | 163 | return tegra114_boot_secondary(cpu, idle); | |
150 | /* | 164 | |
151 | * Unhalt the CPU. If the flow controller was used to power-gate the | 165 | return -EINVAL; |
152 | * CPU this will cause the flow controller to stop driving reset. | ||
153 | * The CPU will remain in reset because the clock and reset block | ||
154 | * is now driving reset. | ||
155 | */ | ||
156 | flowctrl_write_cpu_halt(cpu, 0); | ||
157 | |||
158 | switch (tegra_chip_id) { | ||
159 | case TEGRA20: | ||
160 | status = tegra20_power_up_cpu(cpu); | ||
161 | break; | ||
162 | case TEGRA30: | ||
163 | status = tegra30_power_up_cpu(cpu); | ||
164 | break; | ||
165 | default: | ||
166 | status = -EINVAL; | ||
167 | break; | ||
168 | } | ||
169 | |||
170 | if (status) | ||
171 | goto done; | ||
172 | |||
173 | /* Take the CPU out of reset. */ | ||
174 | tegra_cpu_out_of_reset(cpu); | ||
175 | done: | ||
176 | return status; | ||
177 | } | 166 | } |
178 | 167 | ||
179 | static void __init tegra_smp_prepare_cpus(unsigned int max_cpus) | 168 | static void __init tegra_smp_prepare_cpus(unsigned int max_cpus) |