blob: f80e2d7b0a1c03ad81ee92b515028ca4c5bcc0e3 [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>
Achin Gupta4f6ad662013-10-25 09:08:21 +010037#include <psci.h>
Dan Handley4d2e49d2014-04-11 11:52:12 +010038#include "drivers/pwrc/fvp_pwrc.h"
Achin Gupta4f6ad662013-10-25 09:08:21 +010039
40/*******************************************************************************
Vikram Kanigiri3b7c59b2014-03-21 11:57:10 +000041 * FVP handler called when an affinity instance is about to enter standby.
42 ******************************************************************************/
43int fvp_affinst_standby(unsigned int power_state)
44{
45 unsigned int target_afflvl;
46
47 /* Sanity check the requested state */
48 target_afflvl = psci_get_pstate_afflvl(power_state);
49
50 /*
51 * It's possible to enter standby only on affinity level 0 i.e. a cpu
52 * on the FVP. Ignore any other affinity level.
53 */
54 if (target_afflvl != MPIDR_AFFLVL0)
55 return PSCI_E_INVALID_PARAMS;
56
Andrew Thoelke42e75a72014-04-28 12:28:39 +010057 /*
58 * Enter standby state
59 * dsb is good practice before using wfi to enter low power states
60 */
61 dsb();
Vikram Kanigiri3b7c59b2014-03-21 11:57:10 +000062 wfi();
63
64 return PSCI_E_SUCCESS;
65}
66
67/*******************************************************************************
Achin Gupta4f6ad662013-10-25 09:08:21 +010068 * FVP handler called when an affinity instance is about to be turned on. The
69 * level and mpidr determine the affinity instance.
70 ******************************************************************************/
71int fvp_affinst_on(unsigned long mpidr,
72 unsigned long sec_entrypoint,
73 unsigned long ns_entrypoint,
74 unsigned int afflvl,
75 unsigned int state)
76{
77 int rc = PSCI_E_SUCCESS;
78 unsigned long linear_id;
Dan Handleye2712bc2014-04-10 15:37:22 +010079 mailbox_t *fvp_mboxes;
Achin Gupta4f6ad662013-10-25 09:08:21 +010080 unsigned int psysr;
81
Achin Gupta4f6ad662013-10-25 09:08:21 +010082 /*
83 * It's possible to turn on only affinity level 0 i.e. a cpu
84 * on the FVP. Ignore any other affinity level.
85 */
86 if (afflvl != MPIDR_AFFLVL0)
87 goto exit;
88
89 /*
90 * Ensure that we do not cancel an inflight power off request
91 * for the target cpu. That would leave it in a zombie wfi.
92 * Wait for it to power off, program the jump address for the
93 * target cpu and then program the power controller to turn
94 * that cpu on
95 */
96 do {
97 psysr = fvp_pwrc_read_psysr(mpidr);
98 } while (psysr & PSYSR_AFF_L0);
99
100 linear_id = platform_get_core_pos(mpidr);
Dan Handleye2712bc2014-04-10 15:37:22 +0100101 fvp_mboxes = (mailbox_t *) (TZDRAM_BASE + MBOX_OFF);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100102 fvp_mboxes[linear_id].value = sec_entrypoint;
103 flush_dcache_range((unsigned long) &fvp_mboxes[linear_id],
104 sizeof(unsigned long));
105
106 fvp_pwrc_write_pponr(mpidr);
107
108exit:
109 return rc;
110}
111
112/*******************************************************************************
113 * FVP handler called when an affinity instance is about to be turned off. The
114 * level and mpidr determine the affinity instance. The 'state' arg. allows the
115 * platform to decide whether the cluster is being turned off and take apt
116 * actions.
117 *
118 * CAUTION: This function is called with coherent stacks so that caches can be
119 * turned off, flushed and coherency disabled. There is no guarantee that caches
120 * will remain turned on across calls to this function as each affinity level is
121 * dealt with. So do not write & read global variables across calls. It will be
122 * wise to do flush a write to the global to prevent unpredictable results.
123 ******************************************************************************/
124int fvp_affinst_off(unsigned long mpidr,
125 unsigned int afflvl,
126 unsigned int state)
127{
128 int rc = PSCI_E_SUCCESS;
129 unsigned int gicc_base, ectlr;
Harry Liebel30affd52013-10-30 17:41:48 +0000130 unsigned long cpu_setup, cci_setup;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100131
132 switch (afflvl) {
133 case MPIDR_AFFLVL1:
134 if (state == PSCI_STATE_OFF) {
135 /*
136 * Disable coherency if this cluster is to be
137 * turned off
138 */
Harry Liebel30affd52013-10-30 17:41:48 +0000139 cci_setup = platform_get_cfgvar(CONFIG_HAS_CCI);
140 if (cci_setup) {
141 cci_disable_coherency(mpidr);
142 }
Achin Gupta4f6ad662013-10-25 09:08:21 +0100143
144 /*
145 * Program the power controller to turn the
146 * cluster off
147 */
148 fvp_pwrc_write_pcoffr(mpidr);
149
150 }
151 break;
152
153 case MPIDR_AFFLVL0:
154 if (state == PSCI_STATE_OFF) {
155
156 /*
157 * Take this cpu out of intra-cluster coherency if
158 * the FVP flavour supports the SMP bit.
159 */
160 cpu_setup = platform_get_cfgvar(CONFIG_CPU_SETUP);
161 if (cpu_setup) {
162 ectlr = read_cpuectlr();
163 ectlr &= ~CPUECTLR_SMP_BIT;
164 write_cpuectlr(ectlr);
165 }
166
167 /*
168 * Prevent interrupts from spuriously waking up
169 * this cpu
170 */
171 gicc_base = platform_get_cfgvar(CONFIG_GICC_ADDR);
172 gic_cpuif_deactivate(gicc_base);
173
174 /*
175 * Program the power controller to power this
176 * cpu off
177 */
178 fvp_pwrc_write_ppoffr(mpidr);
179 }
180 break;
181
182 default:
183 assert(0);
184 }
185
186 return rc;
187}
188
189/*******************************************************************************
190 * FVP handler called when an affinity instance is about to be suspended. The
191 * level and mpidr determine the affinity instance. The 'state' arg. allows the
192 * platform to decide whether the cluster is being turned off and take apt
193 * actions.
194 *
195 * CAUTION: This function is called with coherent stacks so that caches can be
196 * turned off, flushed and coherency disabled. There is no guarantee that caches
197 * will remain turned on across calls to this function as each affinity level is
198 * dealt with. So do not write & read global variables across calls. It will be
199 * wise to do flush a write to the global to prevent unpredictable results.
200 ******************************************************************************/
201int fvp_affinst_suspend(unsigned long mpidr,
202 unsigned long sec_entrypoint,
203 unsigned long ns_entrypoint,
204 unsigned int afflvl,
205 unsigned int state)
206{
207 int rc = PSCI_E_SUCCESS;
208 unsigned int gicc_base, ectlr;
Harry Liebel30affd52013-10-30 17:41:48 +0000209 unsigned long cpu_setup, cci_setup, linear_id;
Dan Handleye2712bc2014-04-10 15:37:22 +0100210 mailbox_t *fvp_mboxes;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100211
Achin Gupta4f6ad662013-10-25 09:08:21 +0100212 switch (afflvl) {
213 case MPIDR_AFFLVL1:
214 if (state == PSCI_STATE_OFF) {
215 /*
216 * Disable coherency if this cluster is to be
217 * turned off
218 */
Harry Liebel30affd52013-10-30 17:41:48 +0000219 cci_setup = platform_get_cfgvar(CONFIG_HAS_CCI);
220 if (cci_setup) {
221 cci_disable_coherency(mpidr);
222 }
Achin Gupta4f6ad662013-10-25 09:08:21 +0100223
224 /*
225 * Program the power controller to turn the
226 * cluster off
227 */
228 fvp_pwrc_write_pcoffr(mpidr);
229
230 }
231 break;
232
233 case MPIDR_AFFLVL0:
234 if (state == PSCI_STATE_OFF) {
235 /*
236 * Take this cpu out of intra-cluster coherency if
237 * the FVP flavour supports the SMP bit.
238 */
239 cpu_setup = platform_get_cfgvar(CONFIG_CPU_SETUP);
240 if (cpu_setup) {
241 ectlr = read_cpuectlr();
242 ectlr &= ~CPUECTLR_SMP_BIT;
243 write_cpuectlr(ectlr);
244 }
245
246 /* Program the jump address for the target cpu */
247 linear_id = platform_get_core_pos(mpidr);
Dan Handleye2712bc2014-04-10 15:37:22 +0100248 fvp_mboxes = (mailbox_t *) (TZDRAM_BASE + MBOX_OFF);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100249 fvp_mboxes[linear_id].value = sec_entrypoint;
250 flush_dcache_range((unsigned long) &fvp_mboxes[linear_id],
251 sizeof(unsigned long));
252
253 /*
254 * Prevent interrupts from spuriously waking up
255 * this cpu
256 */
257 gicc_base = platform_get_cfgvar(CONFIG_GICC_ADDR);
258 gic_cpuif_deactivate(gicc_base);
259
260 /*
261 * Program the power controller to power this
262 * cpu off and enable wakeup interrupts.
263 */
Achin Guptab127cdb2013-11-12 16:40:00 +0000264 fvp_pwrc_set_wen(mpidr);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100265 fvp_pwrc_write_ppoffr(mpidr);
266 }
267 break;
268
269 default:
270 assert(0);
271 }
272
Achin Gupta4f6ad662013-10-25 09:08:21 +0100273 return rc;
274}
275
276/*******************************************************************************
277 * FVP handler called when an affinity instance has just been powered on after
278 * being turned off earlier. The level and mpidr determine the affinity
279 * instance. The 'state' arg. allows the platform to decide whether the cluster
280 * was turned off prior to wakeup and do what's necessary to setup it up
281 * correctly.
282 ******************************************************************************/
283int fvp_affinst_on_finish(unsigned long mpidr,
284 unsigned int afflvl,
285 unsigned int state)
286{
287 int rc = PSCI_E_SUCCESS;
Harry Liebel30affd52013-10-30 17:41:48 +0000288 unsigned long linear_id, cpu_setup, cci_setup;
Dan Handleye2712bc2014-04-10 15:37:22 +0100289 mailbox_t *fvp_mboxes;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100290 unsigned int gicd_base, gicc_base, reg_val, ectlr;
291
292 switch (afflvl) {
293
294 case MPIDR_AFFLVL1:
295 /* Enable coherency if this cluster was off */
Harry Liebel30affd52013-10-30 17:41:48 +0000296 if (state == PSCI_STATE_OFF) {
Achin Guptab2187ab2014-01-17 16:52:29 +0000297
298 /*
299 * This CPU might have woken up whilst the
300 * cluster was attempting to power down. In
301 * this case the FVP power controller will
302 * have a pending cluster power off request
303 * which needs to be cleared by writing to the
304 * PPONR register. This prevents the power
305 * controller from interpreting a subsequent
306 * entry of this cpu into a simple wfi as a
307 * power down request.
308 */
309 fvp_pwrc_write_pponr(mpidr);
310
Harry Liebel30affd52013-10-30 17:41:48 +0000311 cci_setup = platform_get_cfgvar(CONFIG_HAS_CCI);
312 if (cci_setup) {
313 cci_enable_coherency(mpidr);
314 }
315 }
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 */
328 cpu_setup = platform_get_cfgvar(CONFIG_CPU_SETUP);
329 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
348 gicd_base = platform_get_cfgvar(CONFIG_GICD_ADDR);
349 gicc_base = platform_get_cfgvar(CONFIG_GICC_ADDR);
350
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
357 /* Allow access to the System counter timer module */
358 reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT);
359 reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT);
360 reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT);
361 mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(0), reg_val);
362 mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(1), reg_val);
363
364 reg_val = (1 << CNTNSAR_NS_SHIFT(0)) |
365 (1 << CNTNSAR_NS_SHIFT(1));
366 mmio_write_32(SYS_TIMCTL_BASE + CNTNSAR, reg_val);
367
368 break;
369
370 default:
371 assert(0);
372 }
373
374 return rc;
375}
376
377/*******************************************************************************
378 * FVP handler called when an affinity instance has just been powered on after
379 * having been suspended earlier. The level and mpidr determine the affinity
380 * instance.
381 * TODO: At the moment we reuse the on finisher and reinitialize the secure
382 * context. Need to implement a separate suspend finisher.
383 ******************************************************************************/
384int fvp_affinst_suspend_finish(unsigned long mpidr,
385 unsigned int afflvl,
386 unsigned int state)
387{
388 return fvp_affinst_on_finish(mpidr, afflvl, state);
389}
390
391
392/*******************************************************************************
393 * Export the platform handlers to enable psci to invoke them
394 ******************************************************************************/
Dan Handleya4cb68e2014-04-23 13:47:06 +0100395static const plat_pm_ops_t fvp_plat_pm_ops = {
Vikram Kanigiri3b7c59b2014-03-21 11:57:10 +0000396 fvp_affinst_standby,
Achin Gupta4f6ad662013-10-25 09:08:21 +0100397 fvp_affinst_on,
398 fvp_affinst_off,
399 fvp_affinst_suspend,
400 fvp_affinst_on_finish,
401 fvp_affinst_suspend_finish,
402};
403
404/*******************************************************************************
405 * Export the platform specific power ops & initialize the fvp power controller
406 ******************************************************************************/
Dan Handleya4cb68e2014-04-23 13:47:06 +0100407int platform_setup_pm(const plat_pm_ops_t **plat_ops)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100408{
409 *plat_ops = &fvp_plat_pm_ops;
410 return 0;
411}