blob: 03f06e7c60b34e7877b8885a6f1374a4cb65faa3 [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
Dan Handleye83b0ca2014-01-14 18:17:09 +00002 * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
Achin Gupta4f6ad662013-10-25 09:08:21 +01003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
Achin Gupta4f6ad662013-10-25 09:08:21 +010031#include <arch_helpers.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010032#include <assert.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010033#include <bakery_lock.h>
34#include <cci400.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010035#include <mmio.h>
36#include <platform.h>
Dan Handleyed6ff952014-05-14 17:44:19 +010037#include <platform_def.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010038#include <psci.h>
Dan Handley4d2e49d2014-04-11 11:52:12 +010039#include "drivers/pwrc/fvp_pwrc.h"
Dan Handleyed6ff952014-05-14 17:44:19 +010040#include "fvp_def.h"
41#include "fvp_private.h"
Achin Gupta4f6ad662013-10-25 09:08:21 +010042
43/*******************************************************************************
Vikram Kanigiri3b7c59b2014-03-21 11:57:10 +000044 * FVP handler called when an affinity instance is about to enter standby.
45 ******************************************************************************/
46int fvp_affinst_standby(unsigned int power_state)
47{
48 unsigned int target_afflvl;
49
50 /* Sanity check the requested state */
51 target_afflvl = psci_get_pstate_afflvl(power_state);
52
53 /*
54 * It's possible to enter standby only on affinity level 0 i.e. a cpu
55 * on the FVP. Ignore any other affinity level.
56 */
57 if (target_afflvl != MPIDR_AFFLVL0)
58 return PSCI_E_INVALID_PARAMS;
59
Andrew Thoelke42e75a72014-04-28 12:28:39 +010060 /*
61 * Enter standby state
62 * dsb is good practice before using wfi to enter low power states
63 */
64 dsb();
Vikram Kanigiri3b7c59b2014-03-21 11:57:10 +000065 wfi();
66
67 return PSCI_E_SUCCESS;
68}
69
70/*******************************************************************************
Achin Gupta4f6ad662013-10-25 09:08:21 +010071 * FVP handler called when an affinity instance is about to be turned on. The
72 * level and mpidr determine the affinity instance.
73 ******************************************************************************/
74int fvp_affinst_on(unsigned long mpidr,
75 unsigned long sec_entrypoint,
76 unsigned long ns_entrypoint,
77 unsigned int afflvl,
78 unsigned int state)
79{
80 int rc = PSCI_E_SUCCESS;
81 unsigned long linear_id;
Dan Handleye2712bc2014-04-10 15:37:22 +010082 mailbox_t *fvp_mboxes;
Achin Gupta4f6ad662013-10-25 09:08:21 +010083 unsigned int psysr;
84
Achin Gupta4f6ad662013-10-25 09:08:21 +010085 /*
86 * It's possible to turn on only affinity level 0 i.e. a cpu
87 * on the FVP. Ignore any other affinity level.
88 */
89 if (afflvl != MPIDR_AFFLVL0)
90 goto exit;
91
92 /*
93 * Ensure that we do not cancel an inflight power off request
94 * for the target cpu. That would leave it in a zombie wfi.
95 * Wait for it to power off, program the jump address for the
96 * target cpu and then program the power controller to turn
97 * that cpu on
98 */
99 do {
100 psysr = fvp_pwrc_read_psysr(mpidr);
101 } while (psysr & PSYSR_AFF_L0);
102
103 linear_id = platform_get_core_pos(mpidr);
Dan Handleye2712bc2014-04-10 15:37:22 +0100104 fvp_mboxes = (mailbox_t *) (TZDRAM_BASE + MBOX_OFF);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100105 fvp_mboxes[linear_id].value = sec_entrypoint;
106 flush_dcache_range((unsigned long) &fvp_mboxes[linear_id],
107 sizeof(unsigned long));
108
109 fvp_pwrc_write_pponr(mpidr);
110
111exit:
112 return rc;
113}
114
115/*******************************************************************************
116 * FVP handler called when an affinity instance is about to be turned off. The
117 * level and mpidr determine the affinity instance. The 'state' arg. allows the
118 * platform to decide whether the cluster is being turned off and take apt
119 * actions.
120 *
121 * CAUTION: This function is called with coherent stacks so that caches can be
122 * turned off, flushed and coherency disabled. There is no guarantee that caches
123 * will remain turned on across calls to this function as each affinity level is
124 * dealt with. So do not write & read global variables across calls. It will be
125 * wise to do flush a write to the global to prevent unpredictable results.
126 ******************************************************************************/
127int fvp_affinst_off(unsigned long mpidr,
128 unsigned int afflvl,
129 unsigned int state)
130{
131 int rc = PSCI_E_SUCCESS;
132 unsigned int gicc_base, ectlr;
Harry Liebel30affd52013-10-30 17:41:48 +0000133 unsigned long cpu_setup, cci_setup;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100134
135 switch (afflvl) {
136 case MPIDR_AFFLVL1:
137 if (state == PSCI_STATE_OFF) {
138 /*
139 * Disable coherency if this cluster is to be
140 * turned off
141 */
Dan Handleyea451572014-05-15 14:53:30 +0100142 cci_setup = fvp_get_cfgvar(CONFIG_HAS_CCI);
Harry Liebel30affd52013-10-30 17:41:48 +0000143 if (cci_setup) {
144 cci_disable_coherency(mpidr);
145 }
Achin Gupta4f6ad662013-10-25 09:08:21 +0100146
147 /*
148 * Program the power controller to turn the
149 * cluster off
150 */
151 fvp_pwrc_write_pcoffr(mpidr);
152
153 }
154 break;
155
156 case MPIDR_AFFLVL0:
157 if (state == PSCI_STATE_OFF) {
158
159 /*
160 * Take this cpu out of intra-cluster coherency if
161 * the FVP flavour supports the SMP bit.
162 */
Dan Handleyea451572014-05-15 14:53:30 +0100163 cpu_setup = fvp_get_cfgvar(CONFIG_CPU_SETUP);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100164 if (cpu_setup) {
165 ectlr = read_cpuectlr();
166 ectlr &= ~CPUECTLR_SMP_BIT;
167 write_cpuectlr(ectlr);
168 }
169
170 /*
171 * Prevent interrupts from spuriously waking up
172 * this cpu
173 */
Dan Handleyea451572014-05-15 14:53:30 +0100174 gicc_base = fvp_get_cfgvar(CONFIG_GICC_ADDR);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100175 gic_cpuif_deactivate(gicc_base);
176
177 /*
178 * Program the power controller to power this
179 * cpu off
180 */
181 fvp_pwrc_write_ppoffr(mpidr);
182 }
183 break;
184
185 default:
186 assert(0);
187 }
188
189 return rc;
190}
191
192/*******************************************************************************
193 * FVP handler called when an affinity instance is about to be suspended. The
194 * level and mpidr determine the affinity instance. The 'state' arg. allows the
195 * platform to decide whether the cluster is being turned off and take apt
196 * actions.
197 *
198 * CAUTION: This function is called with coherent stacks so that caches can be
199 * turned off, flushed and coherency disabled. There is no guarantee that caches
200 * will remain turned on across calls to this function as each affinity level is
201 * dealt with. So do not write & read global variables across calls. It will be
202 * wise to do flush a write to the global to prevent unpredictable results.
203 ******************************************************************************/
204int fvp_affinst_suspend(unsigned long mpidr,
205 unsigned long sec_entrypoint,
206 unsigned long ns_entrypoint,
207 unsigned int afflvl,
208 unsigned int state)
209{
210 int rc = PSCI_E_SUCCESS;
211 unsigned int gicc_base, ectlr;
Harry Liebel30affd52013-10-30 17:41:48 +0000212 unsigned long cpu_setup, cci_setup, linear_id;
Dan Handleye2712bc2014-04-10 15:37:22 +0100213 mailbox_t *fvp_mboxes;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100214
Achin Gupta4f6ad662013-10-25 09:08:21 +0100215 switch (afflvl) {
216 case MPIDR_AFFLVL1:
217 if (state == PSCI_STATE_OFF) {
218 /*
219 * Disable coherency if this cluster is to be
220 * turned off
221 */
Dan Handleyea451572014-05-15 14:53:30 +0100222 cci_setup = fvp_get_cfgvar(CONFIG_HAS_CCI);
Harry Liebel30affd52013-10-30 17:41:48 +0000223 if (cci_setup) {
224 cci_disable_coherency(mpidr);
225 }
Achin Gupta4f6ad662013-10-25 09:08:21 +0100226
227 /*
228 * Program the power controller to turn the
229 * cluster off
230 */
231 fvp_pwrc_write_pcoffr(mpidr);
232
233 }
234 break;
235
236 case MPIDR_AFFLVL0:
237 if (state == PSCI_STATE_OFF) {
238 /*
239 * Take this cpu out of intra-cluster coherency if
240 * the FVP flavour supports the SMP bit.
241 */
Dan Handleyea451572014-05-15 14:53:30 +0100242 cpu_setup = fvp_get_cfgvar(CONFIG_CPU_SETUP);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100243 if (cpu_setup) {
244 ectlr = read_cpuectlr();
245 ectlr &= ~CPUECTLR_SMP_BIT;
246 write_cpuectlr(ectlr);
247 }
248
249 /* Program the jump address for the target cpu */
250 linear_id = platform_get_core_pos(mpidr);
Dan Handleye2712bc2014-04-10 15:37:22 +0100251 fvp_mboxes = (mailbox_t *) (TZDRAM_BASE + MBOX_OFF);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100252 fvp_mboxes[linear_id].value = sec_entrypoint;
253 flush_dcache_range((unsigned long) &fvp_mboxes[linear_id],
254 sizeof(unsigned long));
255
256 /*
257 * Prevent interrupts from spuriously waking up
258 * this cpu
259 */
Dan Handleyea451572014-05-15 14:53:30 +0100260 gicc_base = fvp_get_cfgvar(CONFIG_GICC_ADDR);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100261 gic_cpuif_deactivate(gicc_base);
262
263 /*
264 * Program the power controller to power this
265 * cpu off and enable wakeup interrupts.
266 */
Achin Guptab127cdb2013-11-12 16:40:00 +0000267 fvp_pwrc_set_wen(mpidr);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100268 fvp_pwrc_write_ppoffr(mpidr);
269 }
270 break;
271
272 default:
273 assert(0);
274 }
275
Achin Gupta4f6ad662013-10-25 09:08:21 +0100276 return rc;
277}
278
279/*******************************************************************************
280 * FVP handler called when an affinity instance has just been powered on after
281 * being turned off earlier. The level and mpidr determine the affinity
282 * instance. The 'state' arg. allows the platform to decide whether the cluster
283 * was turned off prior to wakeup and do what's necessary to setup it up
284 * correctly.
285 ******************************************************************************/
286int fvp_affinst_on_finish(unsigned long mpidr,
287 unsigned int afflvl,
288 unsigned int state)
289{
290 int rc = PSCI_E_SUCCESS;
Vikram Kanigiri96377452014-04-24 11:02:16 +0100291 unsigned long linear_id, cpu_setup;
Dan Handleye2712bc2014-04-10 15:37:22 +0100292 mailbox_t *fvp_mboxes;
Soby Mathewbb128912014-06-06 10:18:52 +0100293 unsigned int gicd_base, gicc_base, ectlr;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100294
295 switch (afflvl) {
296
297 case MPIDR_AFFLVL1:
298 /* Enable coherency if this cluster was off */
Harry Liebel30affd52013-10-30 17:41:48 +0000299 if (state == PSCI_STATE_OFF) {
Achin Guptab2187ab2014-01-17 16:52:29 +0000300
301 /*
302 * This CPU might have woken up whilst the
303 * cluster was attempting to power down. In
304 * this case the FVP power controller will
305 * have a pending cluster power off request
306 * which needs to be cleared by writing to the
307 * PPONR register. This prevents the power
308 * controller from interpreting a subsequent
309 * entry of this cpu into a simple wfi as a
310 * power down request.
311 */
312 fvp_pwrc_write_pponr(mpidr);
313
Vikram Kanigiri96377452014-04-24 11:02:16 +0100314 fvp_cci_setup();
Harry Liebel30affd52013-10-30 17:41:48 +0000315 }
Achin Gupta4f6ad662013-10-25 09:08:21 +0100316 break;
317
318 case MPIDR_AFFLVL0:
319 /*
320 * Ignore the state passed for a cpu. It could only have
321 * been off if we are here.
322 */
323
324 /*
325 * Turn on intra-cluster coherency if the FVP flavour supports
326 * it.
327 */
Dan Handleyea451572014-05-15 14:53:30 +0100328 cpu_setup = fvp_get_cfgvar(CONFIG_CPU_SETUP);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100329 if (cpu_setup) {
330 ectlr = read_cpuectlr();
331 ectlr |= CPUECTLR_SMP_BIT;
332 write_cpuectlr(ectlr);
333 }
334
Achin Guptab127cdb2013-11-12 16:40:00 +0000335 /*
336 * Clear PWKUPR.WEN bit to ensure interrupts do not interfere
337 * with a cpu power down unless the bit is set again
338 */
339 fvp_pwrc_clr_wen(mpidr);
340
Achin Gupta4f6ad662013-10-25 09:08:21 +0100341 /* Zero the jump address in the mailbox for this cpu */
Dan Handleye2712bc2014-04-10 15:37:22 +0100342 fvp_mboxes = (mailbox_t *) (TZDRAM_BASE + MBOX_OFF);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100343 linear_id = platform_get_core_pos(mpidr);
344 fvp_mboxes[linear_id].value = 0;
345 flush_dcache_range((unsigned long) &fvp_mboxes[linear_id],
346 sizeof(unsigned long));
347
Dan Handleyea451572014-05-15 14:53:30 +0100348 gicd_base = fvp_get_cfgvar(CONFIG_GICD_ADDR);
349 gicc_base = fvp_get_cfgvar(CONFIG_GICC_ADDR);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100350
351 /* Enable the gic cpu interface */
352 gic_cpuif_setup(gicc_base);
353
354 /* TODO: This setup is needed only after a cold boot */
355 gic_pcpu_distif_setup(gicd_base);
356
Achin Gupta4f6ad662013-10-25 09:08:21 +0100357 break;
358
359 default:
360 assert(0);
361 }
362
363 return rc;
364}
365
366/*******************************************************************************
367 * FVP handler called when an affinity instance has just been powered on after
368 * having been suspended earlier. The level and mpidr determine the affinity
369 * instance.
370 * TODO: At the moment we reuse the on finisher and reinitialize the secure
371 * context. Need to implement a separate suspend finisher.
372 ******************************************************************************/
373int fvp_affinst_suspend_finish(unsigned long mpidr,
374 unsigned int afflvl,
375 unsigned int state)
376{
377 return fvp_affinst_on_finish(mpidr, afflvl, state);
378}
379
380
381/*******************************************************************************
382 * Export the platform handlers to enable psci to invoke them
383 ******************************************************************************/
Dan Handleya4cb68e2014-04-23 13:47:06 +0100384static const plat_pm_ops_t fvp_plat_pm_ops = {
Vikram Kanigiri3b7c59b2014-03-21 11:57:10 +0000385 fvp_affinst_standby,
Achin Gupta4f6ad662013-10-25 09:08:21 +0100386 fvp_affinst_on,
387 fvp_affinst_off,
388 fvp_affinst_suspend,
389 fvp_affinst_on_finish,
390 fvp_affinst_suspend_finish,
391};
392
393/*******************************************************************************
394 * Export the platform specific power ops & initialize the fvp power controller
395 ******************************************************************************/
Dan Handleya4cb68e2014-04-23 13:47:06 +0100396int platform_setup_pm(const plat_pm_ops_t **plat_ops)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100397{
398 *plat_ops = &fvp_plat_pm_ops;
399 return 0;
400}