blob: 27a12278d39513f428c0de006ad6575af644ef03 [file] [log] [blame]
Sandrine Bailleux798140d2014-07-17 16:06:39 +01001/*
2 * Copyright (c) 2013, ARM Limited and Contributors. All rights reserved.
3 *
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
31#include <assert.h>
32#include <arch_helpers.h>
33#include <cci400.h>
34#include <errno.h>
35#include <platform.h>
36#include <platform_def.h>
37#include <psci.h>
38#include "juno_def.h"
39#include "juno_private.h"
40#include "scpi.h"
41
42/*******************************************************************************
43 * Private Juno function to program the mailbox for a cpu before it is released
44 * from reset.
45 ******************************************************************************/
46static void juno_program_mailbox(uint64_t mpidr, uint64_t address)
47{
48 uint64_t linear_id;
49 uint64_t mbox;
50
51 linear_id = platform_get_core_pos(mpidr);
52 mbox = TRUSTED_MAILBOXES_BASE + (linear_id << TRUSTED_MAILBOX_SHIFT);
53 *((uint64_t *) mbox) = address;
54 flush_dcache_range(mbox, sizeof(mbox));
55}
56
57/*******************************************************************************
58 * Private Juno function which is used to determine if any platform actions
59 * should be performed for the specified affinity instance given its
60 * state. Nothing needs to be done if the 'state' is not off or if this is not
61 * the highest affinity level which will enter the 'state'.
62 ******************************************************************************/
63static int32_t juno_do_plat_actions(uint32_t afflvl, uint32_t state)
64{
65 uint32_t max_phys_off_afflvl;
66
67 assert(afflvl <= MPIDR_AFFLVL1);
68
69 if (state != PSCI_STATE_OFF)
70 return -EAGAIN;
71
72 /*
73 * Find the highest affinity level which will be suspended and postpone
74 * all the platform specific actions until that level is hit.
75 */
76 max_phys_off_afflvl = psci_get_max_phys_off_afflvl();
77 assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
78 assert(psci_get_suspend_afflvl() >= max_phys_off_afflvl);
79 if (afflvl != max_phys_off_afflvl)
80 return -EAGAIN;
81
82 return 0;
83}
84
85/*******************************************************************************
86 * Juno handler called when an affinity instance is about to be turned on. The
87 * level and mpidr determine the affinity instance.
88 ******************************************************************************/
Achin Gupta89b70cd2014-08-18 14:40:27 +010089int32_t juno_affinst_on(uint64_t mpidr,
90 uint64_t sec_entrypoint,
91 uint64_t ns_entrypoint,
92 uint32_t afflvl,
93 uint32_t state)
Sandrine Bailleux798140d2014-07-17 16:06:39 +010094{
95 /*
96 * SCP takes care of powering up higher affinity levels so we
97 * only need to care about level 0
98 */
99 if (afflvl != MPIDR_AFFLVL0)
100 return PSCI_E_SUCCESS;
101
102 /*
103 * Setup mailbox with address for CPU entrypoint when it next powers up
104 */
105 juno_program_mailbox(mpidr, sec_entrypoint);
106
107 scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on,
108 scpi_power_on);
109
110 return PSCI_E_SUCCESS;
111}
112
113/*******************************************************************************
114 * Juno handler called when an affinity instance has just been powered on after
115 * being turned off earlier. The level and mpidr determine the affinity
116 * instance. The 'state' arg. allows the platform to decide whether the cluster
117 * was turned off prior to wakeup and do what's necessary to setup it up
118 * correctly.
119 ******************************************************************************/
Achin Gupta89b70cd2014-08-18 14:40:27 +0100120int32_t juno_affinst_on_finish(uint64_t mpidr, uint32_t afflvl, uint32_t state)
Sandrine Bailleux798140d2014-07-17 16:06:39 +0100121{
122 /* Determine if any platform actions need to be executed. */
123 if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
124 return PSCI_E_SUCCESS;
125
126 /*
127 * Perform the common cluster specific operations i.e enable coherency
128 * if this cluster was off.
129 */
130 if (afflvl != MPIDR_AFFLVL0)
131 cci_enable_cluster_coherency(mpidr);
132
133
134 /* Enable the gic cpu interface */
135 gic_cpuif_setup(GICC_BASE);
136
137 /* Juno todo: Is this setup only needed after a cold boot? */
138 gic_pcpu_distif_setup(GICD_BASE);
139
140 /* Clear the mailbox for this cpu. */
141 juno_program_mailbox(mpidr, 0);
142
143 return PSCI_E_SUCCESS;
144}
145
146/*******************************************************************************
Achin Gupta89b70cd2014-08-18 14:40:27 +0100147 * Common function called while turning a cpu off or suspending it. It is called
148 * from juno_off() or juno_suspend() when these functions in turn are called for
149 * the highest affinity level which will be powered down. It performs the
150 * actions common to the OFF and SUSPEND calls.
151 ******************************************************************************/
152static int32_t juno_power_down_common(uint32_t afflvl)
153{
154 uint32_t cluster_state = scpi_power_on;
155
156 /* Prevent interrupts from spuriously waking up this cpu */
157 gic_cpuif_deactivate(GICC_BASE);
158
159 /* Cluster is to be turned off, so disable coherency */
160 if (afflvl > MPIDR_AFFLVL0) {
161 cci_disable_cluster_coherency(read_mpidr_el1());
162 cluster_state = scpi_power_off;
163 }
164
165 /*
166 * Ask the SCP to power down the appropriate components depending upon
167 * their state.
168 */
169 scpi_set_css_power_state(read_mpidr_el1(),
170 scpi_power_off,
171 cluster_state,
172 scpi_power_on);
173
174 return PSCI_E_SUCCESS;
175}
176
177/*******************************************************************************
178 * Handler called when an affinity instance is about to be turned off. The
179 * level and mpidr determine the affinity instance. The 'state' arg. allows the
180 * platform to decide whether the cluster is being turned off and take
181 * appropriate actions.
182 *
183 * CAUTION: There is no guarantee that caches will remain turned on across calls
184 * to this function as each affinity level is dealt with. So do not write & read
185 * global variables across calls. It will be wise to do flush a write to the
186 * global to prevent unpredictable results.
187 ******************************************************************************/
188static int32_t juno_affinst_off(uint64_t mpidr, uint32_t afflvl, uint32_t state)
189{
190 /* Determine if any platform actions need to be executed */
191 if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
192 return PSCI_E_SUCCESS;
193
194 return juno_power_down_common(afflvl);
195}
196
197/*******************************************************************************
198 * Handler called when an affinity instance is about to be suspended. The
199 * level and mpidr determine the affinity instance. The 'state' arg. allows the
200 * platform to decide whether the cluster is being turned off and take apt
201 * actions. The 'sec_entrypoint' determines the address in BL3-1 from where
202 * execution should resume.
203 *
204 * CAUTION: There is no guarantee that caches will remain turned on across calls
205 * to this function as each affinity level is dealt with. So do not write & read
206 * global variables across calls. It will be wise to do flush a write to the
207 * global to prevent unpredictable results.
208 ******************************************************************************/
209static int32_t juno_affinst_suspend(uint64_t mpidr,
210 uint64_t sec_entrypoint,
211 uint64_t ns_entrypoint,
212 uint32_t afflvl,
213 uint32_t state)
214{
215 /* Determine if any platform actions need to be executed */
216 if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
217 return PSCI_E_SUCCESS;
218
219 /*
220 * Setup mailbox with address for CPU entrypoint when it next powers up.
221 */
222 juno_program_mailbox(mpidr, sec_entrypoint);
223
224 return juno_power_down_common(afflvl);
225}
226
227/*******************************************************************************
228 * Juno handler called when an affinity instance has just been powered on after
229 * having been suspended earlier. The level and mpidr determine the affinity
230 * instance.
231 * TODO: At the moment we reuse the on finisher and reinitialize the secure
232 * context. Need to implement a separate suspend finisher.
233 ******************************************************************************/
234static int32_t juno_affinst_suspend_finish(uint64_t mpidr,
235 uint32_t afflvl,
236 uint32_t state)
237{
238 return juno_affinst_on_finish(mpidr, afflvl, state);
239}
240
241/*******************************************************************************
Sandrine Bailleux798140d2014-07-17 16:06:39 +0100242 * Export the platform handlers to enable psci to invoke them
243 ******************************************************************************/
244static const plat_pm_ops_t juno_ops = {
Achin Gupta89b70cd2014-08-18 14:40:27 +0100245 .affinst_on = juno_affinst_on,
246 .affinst_on_finish = juno_affinst_on_finish,
247 .affinst_off = juno_affinst_off,
248 .affinst_suspend = juno_affinst_suspend,
249 .affinst_suspend_finish = juno_affinst_suspend_finish
Sandrine Bailleux798140d2014-07-17 16:06:39 +0100250};
251
252/*******************************************************************************
253 * Export the platform specific power ops.
254 ******************************************************************************/
255int32_t platform_setup_pm(const plat_pm_ops_t **plat_ops)
256{
257 *plat_ops = &juno_ops;
258 return 0;
259}