blob: 568b51d9f9b88144d4659e8f7c73001c6bc9e5db [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 Handleyfb42b122014-06-20 09:43:15 +010032#include <arm_gic.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010033#include <assert.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010034#include <bakery_lock.h>
35#include <cci400.h>
Juan Castillo4dc4a472014-08-12 11:17:06 +010036#include <debug.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010037#include <mmio.h>
38#include <platform.h>
Dan Handley1c54d972014-06-20 12:02:01 +010039#include <plat_config.h>
Dan Handleyed6ff952014-05-14 17:44:19 +010040#include <platform_def.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010041#include <psci.h>
Achin Gupta85876392014-07-31 17:45:51 +010042#include <errno.h>
Dan Handley4d2e49d2014-04-11 11:52:12 +010043#include "drivers/pwrc/fvp_pwrc.h"
Dan Handleyed6ff952014-05-14 17:44:19 +010044#include "fvp_def.h"
45#include "fvp_private.h"
Achin Gupta4f6ad662013-10-25 09:08:21 +010046
47/*******************************************************************************
Achin Gupta85876392014-07-31 17:45:51 +010048 * Private FVP function to program the mailbox for a cpu before it is released
49 * from reset.
50 ******************************************************************************/
51static void fvp_program_mailbox(uint64_t mpidr, uint64_t address)
52{
53 uint64_t linear_id;
54 mailbox_t *fvp_mboxes;
55
56 linear_id = platform_get_core_pos(mpidr);
57 fvp_mboxes = (mailbox_t *)MBOX_BASE;
58 fvp_mboxes[linear_id].value = address;
59 flush_dcache_range((unsigned long) &fvp_mboxes[linear_id],
60 sizeof(unsigned long));
61}
62
63/*******************************************************************************
64 * Function which implements the common FVP specific operations to power down a
65 * cpu in response to a CPU_OFF or CPU_SUSPEND request.
66 ******************************************************************************/
67static void fvp_cpu_pwrdwn_common()
68{
69 uint32_t ectlr;
70
71 /*
72 * Take this cpu out of intra-cluster coherency if the FVP flavour
73 * supports the SMP bit.
74 */
75 if (get_plat_config()->flags & CONFIG_CPUECTLR_SMP_BIT) {
76 ectlr = read_cpuectlr();
77 ectlr &= ~CPUECTLR_SMP_BIT;
78 write_cpuectlr(ectlr);
79 }
80
81 /* Prevent interrupts from spuriously waking up this cpu */
82 arm_gic_cpuif_deactivate();
83
84 /* Program the power controller to power off this cpu. */
85 fvp_pwrc_write_ppoffr(read_mpidr_el1());
86}
87
88/*******************************************************************************
89 * Function which implements the common FVP specific operations to power down a
90 * cluster in response to a CPU_OFF or CPU_SUSPEND request.
91 ******************************************************************************/
92static void fvp_cluster_pwrdwn_common()
93{
94 uint64_t mpidr = read_mpidr_el1();
95
96 /* Disable coherency if this cluster is to be turned off */
97 if (get_plat_config()->flags & CONFIG_HAS_CCI)
98 cci_disable_cluster_coherency(mpidr);
99
100 /* Program the power controller to turn the cluster off */
101 fvp_pwrc_write_pcoffr(mpidr);
102}
103
104/*******************************************************************************
105 * Private FVP function which is used to determine if any platform actions
106 * should be performed for the specified affinity instance given its
107 * state. Nothing needs to be done if the 'state' is not off or if this is not
108 * the highest affinity level which will enter the 'state'.
109 ******************************************************************************/
110static int32_t fvp_do_plat_actions(unsigned int afflvl, unsigned int state)
111{
112 unsigned int max_phys_off_afflvl;
113
114 assert(afflvl <= MPIDR_AFFLVL1);
115
116 if (state != PSCI_STATE_OFF)
117 return -EAGAIN;
118
119 /*
120 * Find the highest affinity level which will be suspended and postpone
121 * all the platform specific actions until that level is hit.
122 */
123 max_phys_off_afflvl = psci_get_max_phys_off_afflvl();
124 assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
125 if (afflvl != max_phys_off_afflvl)
126 return -EAGAIN;
127
128 return 0;
129}
130
131/*******************************************************************************
Vikram Kanigiri3b7c59b2014-03-21 11:57:10 +0000132 * FVP handler called when an affinity instance is about to enter standby.
133 ******************************************************************************/
134int fvp_affinst_standby(unsigned int power_state)
135{
136 unsigned int target_afflvl;
137
138 /* Sanity check the requested state */
139 target_afflvl = psci_get_pstate_afflvl(power_state);
140
141 /*
142 * It's possible to enter standby only on affinity level 0 i.e. a cpu
143 * on the FVP. Ignore any other affinity level.
144 */
145 if (target_afflvl != MPIDR_AFFLVL0)
146 return PSCI_E_INVALID_PARAMS;
147
Andrew Thoelke42e75a72014-04-28 12:28:39 +0100148 /*
149 * Enter standby state
150 * dsb is good practice before using wfi to enter low power states
151 */
152 dsb();
Vikram Kanigiri3b7c59b2014-03-21 11:57:10 +0000153 wfi();
154
155 return PSCI_E_SUCCESS;
156}
157
158/*******************************************************************************
Achin Gupta4f6ad662013-10-25 09:08:21 +0100159 * FVP handler called when an affinity instance is about to be turned on. The
160 * level and mpidr determine the affinity instance.
161 ******************************************************************************/
162int fvp_affinst_on(unsigned long mpidr,
163 unsigned long sec_entrypoint,
164 unsigned long ns_entrypoint,
165 unsigned int afflvl,
166 unsigned int state)
167{
168 int rc = PSCI_E_SUCCESS;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100169 unsigned int psysr;
170
Achin Gupta4f6ad662013-10-25 09:08:21 +0100171 /*
172 * It's possible to turn on only affinity level 0 i.e. a cpu
173 * on the FVP. Ignore any other affinity level.
174 */
175 if (afflvl != MPIDR_AFFLVL0)
Achin Gupta85876392014-07-31 17:45:51 +0100176 return rc;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100177
178 /*
179 * Ensure that we do not cancel an inflight power off request
180 * for the target cpu. That would leave it in a zombie wfi.
181 * Wait for it to power off, program the jump address for the
182 * target cpu and then program the power controller to turn
183 * that cpu on
184 */
185 do {
186 psysr = fvp_pwrc_read_psysr(mpidr);
187 } while (psysr & PSYSR_AFF_L0);
188
Achin Gupta85876392014-07-31 17:45:51 +0100189 fvp_program_mailbox(mpidr, sec_entrypoint);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100190 fvp_pwrc_write_pponr(mpidr);
191
Achin Gupta4f6ad662013-10-25 09:08:21 +0100192 return rc;
193}
194
195/*******************************************************************************
196 * FVP handler called when an affinity instance is about to be turned off. The
197 * level and mpidr determine the affinity instance. The 'state' arg. allows the
198 * platform to decide whether the cluster is being turned off and take apt
199 * actions.
200 *
Achin Gupta9c60d802014-06-26 11:12:37 +0100201 * CAUTION: There is no guarantee that caches will remain turned on across calls
202 * to this function as each affinity level is dealt with. So do not write & read
203 * global variables across calls. It will be wise to do flush a write to the
204 * global to prevent unpredictable results.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100205 ******************************************************************************/
206int fvp_affinst_off(unsigned long mpidr,
207 unsigned int afflvl,
208 unsigned int state)
209{
Achin Gupta85876392014-07-31 17:45:51 +0100210 /* Determine if any platform actions need to be executed */
211 if (fvp_do_plat_actions(afflvl, state) == -EAGAIN)
212 return PSCI_E_SUCCESS;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100213
Achin Gupta85876392014-07-31 17:45:51 +0100214 /*
215 * If execution reaches this stage then this affinity level will be
216 * suspended. Perform at least the cpu specific actions followed the
217 * cluster specific operations if applicable.
218 */
219 fvp_cpu_pwrdwn_common();
Achin Gupta4f6ad662013-10-25 09:08:21 +0100220
Achin Gupta85876392014-07-31 17:45:51 +0100221 if (afflvl != MPIDR_AFFLVL0)
222 fvp_cluster_pwrdwn_common();
Achin Gupta4f6ad662013-10-25 09:08:21 +0100223
Achin Gupta85876392014-07-31 17:45:51 +0100224 return PSCI_E_SUCCESS;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100225}
226
227/*******************************************************************************
228 * FVP handler called when an affinity instance is about to be suspended. The
229 * level and mpidr determine the affinity instance. The 'state' arg. allows the
230 * platform to decide whether the cluster is being turned off and take apt
231 * actions.
232 *
Achin Gupta9c60d802014-06-26 11:12:37 +0100233 * CAUTION: There is no guarantee that caches will remain turned on across calls
234 * to this function as each affinity level is dealt with. So do not write & read
235 * global variables across calls. It will be wise to do flush a write to the
236 * global to prevent unpredictable results.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100237 ******************************************************************************/
238int fvp_affinst_suspend(unsigned long mpidr,
239 unsigned long sec_entrypoint,
240 unsigned long ns_entrypoint,
241 unsigned int afflvl,
242 unsigned int state)
243{
Achin Gupta85876392014-07-31 17:45:51 +0100244 /* Determine if any platform actions need to be executed. */
245 if (fvp_do_plat_actions(afflvl, state) == -EAGAIN)
246 return PSCI_E_SUCCESS;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100247
Achin Gupta85876392014-07-31 17:45:51 +0100248 /* Program the jump address for the target cpu */
249 fvp_program_mailbox(read_mpidr_el1(), sec_entrypoint);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100250
Achin Gupta85876392014-07-31 17:45:51 +0100251 /* Program the power controller to enable wakeup interrupts. */
252 fvp_pwrc_set_wen(mpidr);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100253
Achin Gupta85876392014-07-31 17:45:51 +0100254 /* Perform the common cpu specific operations */
255 fvp_cpu_pwrdwn_common();
Achin Gupta4f6ad662013-10-25 09:08:21 +0100256
Achin Gupta85876392014-07-31 17:45:51 +0100257 /* Perform the common cluster specific operations */
258 if (afflvl != MPIDR_AFFLVL0)
259 fvp_cluster_pwrdwn_common();
Achin Gupta4f6ad662013-10-25 09:08:21 +0100260
Achin Gupta85876392014-07-31 17:45:51 +0100261 return PSCI_E_SUCCESS;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100262}
263
264/*******************************************************************************
265 * FVP handler called when an affinity instance has just been powered on after
266 * being turned off earlier. The level and mpidr determine the affinity
267 * instance. The 'state' arg. allows the platform to decide whether the cluster
268 * was turned off prior to wakeup and do what's necessary to setup it up
269 * correctly.
270 ******************************************************************************/
271int fvp_affinst_on_finish(unsigned long mpidr,
272 unsigned int afflvl,
273 unsigned int state)
274{
275 int rc = PSCI_E_SUCCESS;
Dan Handleyfb42b122014-06-20 09:43:15 +0100276 unsigned int ectlr;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100277
Achin Gupta85876392014-07-31 17:45:51 +0100278 /* Determine if any platform actions need to be executed. */
279 if (fvp_do_plat_actions(afflvl, state) == -EAGAIN)
280 return PSCI_E_SUCCESS;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100281
Achin Gupta85876392014-07-31 17:45:51 +0100282 /* Perform the common cluster specific operations */
283 if (afflvl != MPIDR_AFFLVL0) {
Achin Gupta4f6ad662013-10-25 09:08:21 +0100284 /*
Achin Gupta85876392014-07-31 17:45:51 +0100285 * This CPU might have woken up whilst the cluster was
286 * attempting to power down. In this case the FVP power
287 * controller will have a pending cluster power off request
288 * which needs to be cleared by writing to the PPONR register.
289 * This prevents the power controller from interpreting a
290 * subsequent entry of this cpu into a simple wfi as a power
291 * down request.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100292 */
Achin Gupta85876392014-07-31 17:45:51 +0100293 fvp_pwrc_write_pponr(mpidr);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100294
Achin Gupta85876392014-07-31 17:45:51 +0100295 /* Enable coherency if this cluster was off */
296 fvp_cci_enable();
297 }
Achin Guptab127cdb2013-11-12 16:40:00 +0000298
Achin Gupta85876392014-07-31 17:45:51 +0100299 /*
300 * Turn on intra-cluster coherency if the FVP flavour supports
301 * it.
302 */
303 if (get_plat_config()->flags & CONFIG_CPUECTLR_SMP_BIT) {
304 ectlr = read_cpuectlr();
305 ectlr |= CPUECTLR_SMP_BIT;
306 write_cpuectlr(ectlr);
307 }
Achin Gupta4f6ad662013-10-25 09:08:21 +0100308
Achin Gupta85876392014-07-31 17:45:51 +0100309 /*
310 * Clear PWKUPR.WEN bit to ensure interrupts do not interfere
311 * with a cpu power down unless the bit is set again
312 */
313 fvp_pwrc_clr_wen(mpidr);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100314
Achin Gupta85876392014-07-31 17:45:51 +0100315 /* Zero the jump address in the mailbox for this cpu */
316 fvp_program_mailbox(read_mpidr_el1(), 0);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100317
Achin Gupta85876392014-07-31 17:45:51 +0100318 /* Enable the gic cpu interface */
319 arm_gic_cpuif_setup();
Achin Gupta4f6ad662013-10-25 09:08:21 +0100320
Achin Gupta85876392014-07-31 17:45:51 +0100321 /* TODO: This setup is needed only after a cold boot */
322 arm_gic_pcpu_distif_setup();
Achin Gupta4f6ad662013-10-25 09:08:21 +0100323
324 return rc;
325}
326
327/*******************************************************************************
328 * FVP handler called when an affinity instance has just been powered on after
329 * having been suspended earlier. The level and mpidr determine the affinity
330 * instance.
331 * TODO: At the moment we reuse the on finisher and reinitialize the secure
332 * context. Need to implement a separate suspend finisher.
333 ******************************************************************************/
334int fvp_affinst_suspend_finish(unsigned long mpidr,
335 unsigned int afflvl,
336 unsigned int state)
337{
338 return fvp_affinst_on_finish(mpidr, afflvl, state);
339}
340
Juan Castillo4dc4a472014-08-12 11:17:06 +0100341/*******************************************************************************
342 * FVP handlers to shutdown/reboot the system
343 ******************************************************************************/
344static void __dead2 fvp_system_off(void)
345{
346 /* Write the System Configuration Control Register */
347 mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGCTRL,
348 CFGCTRL_START | CFGCTRL_RW | CFGCTRL_FUNC(FUNC_SHUTDOWN));
349 wfi();
350 ERROR("FVP System Off: operation not handled.\n");
351 panic();
352}
353
354static void __dead2 fvp_system_reset(void)
355{
356 /* Write the System Configuration Control Register */
357 mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGCTRL,
358 CFGCTRL_START | CFGCTRL_RW | CFGCTRL_FUNC(FUNC_REBOOT));
359 wfi();
360 ERROR("FVP System Reset: operation not handled.\n");
361 panic();
362}
Achin Gupta4f6ad662013-10-25 09:08:21 +0100363
364/*******************************************************************************
365 * Export the platform handlers to enable psci to invoke them
366 ******************************************************************************/
Dan Handleya4cb68e2014-04-23 13:47:06 +0100367static const plat_pm_ops_t fvp_plat_pm_ops = {
Juan Castillo4dc4a472014-08-12 11:17:06 +0100368 .affinst_standby = fvp_affinst_standby,
369 .affinst_on = fvp_affinst_on,
370 .affinst_off = fvp_affinst_off,
371 .affinst_suspend = fvp_affinst_suspend,
372 .affinst_on_finish = fvp_affinst_on_finish,
373 .affinst_suspend_finish = fvp_affinst_suspend_finish,
374 .system_off = fvp_system_off,
375 .system_reset = fvp_system_reset
Achin Gupta4f6ad662013-10-25 09:08:21 +0100376};
377
378/*******************************************************************************
379 * Export the platform specific power ops & initialize the fvp power controller
380 ******************************************************************************/
Dan Handleya4cb68e2014-04-23 13:47:06 +0100381int platform_setup_pm(const plat_pm_ops_t **plat_ops)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100382{
383 *plat_ops = &fvp_plat_pm_ops;
384 return 0;
385}