1 /* 2 * Copyright (c) 2013-2014, 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 <arch_helpers.h> 32 #include <arm_gic.h> 33 #include <assert.h> 34 #include <bakery_lock.h> 35 #include <cci400.h> 36 #include <debug.h> 37 #include <mmio.h> 38 #include <platform.h> 39 #include <plat_config.h> 40 #include <platform_def.h> 41 #include <psci.h> 42 #include <errno.h> 43 #include "drivers/pwrc/fvp_pwrc.h" 44 #include "fvp_def.h" 45 #include "fvp_private.h" 46 47 /******************************************************************************* 48 * Private FVP function to program the mailbox for a cpu before it is released 49 * from reset. 50 ******************************************************************************/ 51 static 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 ******************************************************************************/ 67 static void fvp_cpu_pwrdwn_common() 68 { 69 /* Prevent interrupts from spuriously waking up this cpu */ 70 arm_gic_cpuif_deactivate(); 71 72 /* Program the power controller to power off this cpu. */ 73 fvp_pwrc_write_ppoffr(read_mpidr_el1()); 74 } 75 76 /******************************************************************************* 77 * Function which implements the common FVP specific operations to power down a 78 * cluster in response to a CPU_OFF or CPU_SUSPEND request. 79 ******************************************************************************/ 80 static void fvp_cluster_pwrdwn_common() 81 { 82 uint64_t mpidr = read_mpidr_el1(); 83 84 /* Disable coherency if this cluster is to be turned off */ 85 if (get_plat_config()->flags & CONFIG_HAS_CCI) 86 cci_disable_cluster_coherency(mpidr); 87 88 /* Program the power controller to turn the cluster off */ 89 fvp_pwrc_write_pcoffr(mpidr); 90 } 91 92 /******************************************************************************* 93 * Private FVP function which is used to determine if any platform actions 94 * should be performed for the specified affinity instance given its 95 * state. Nothing needs to be done if the 'state' is not off or if this is not 96 * the highest affinity level which will enter the 'state'. 97 ******************************************************************************/ 98 static int32_t fvp_do_plat_actions(unsigned int afflvl, unsigned int state) 99 { 100 unsigned int max_phys_off_afflvl; 101 102 assert(afflvl <= MPIDR_AFFLVL1); 103 104 if (state != PSCI_STATE_OFF) 105 return -EAGAIN; 106 107 /* 108 * Find the highest affinity level which will be suspended and postpone 109 * all the platform specific actions until that level is hit. 110 */ 111 max_phys_off_afflvl = psci_get_max_phys_off_afflvl(); 112 assert(max_phys_off_afflvl != PSCI_INVALID_DATA); 113 if (afflvl != max_phys_off_afflvl) 114 return -EAGAIN; 115 116 return 0; 117 } 118 119 /******************************************************************************* 120 * FVP handler called when an affinity instance is about to enter standby. 121 ******************************************************************************/ 122 void fvp_affinst_standby(unsigned int power_state) 123 { 124 /* 125 * Enter standby state 126 * dsb is good practice before using wfi to enter low power states 127 */ 128 dsb(); 129 wfi(); 130 } 131 132 /******************************************************************************* 133 * FVP handler called when an affinity instance is about to be turned on. The 134 * level and mpidr determine the affinity instance. 135 ******************************************************************************/ 136 int fvp_affinst_on(unsigned long mpidr, 137 unsigned long sec_entrypoint, 138 unsigned int afflvl, 139 unsigned int state) 140 { 141 int rc = PSCI_E_SUCCESS; 142 unsigned int psysr; 143 144 /* 145 * It's possible to turn on only affinity level 0 i.e. a cpu 146 * on the FVP. Ignore any other affinity level. 147 */ 148 if (afflvl != MPIDR_AFFLVL0) 149 return rc; 150 151 /* 152 * Ensure that we do not cancel an inflight power off request 153 * for the target cpu. That would leave it in a zombie wfi. 154 * Wait for it to power off, program the jump address for the 155 * target cpu and then program the power controller to turn 156 * that cpu on 157 */ 158 do { 159 psysr = fvp_pwrc_read_psysr(mpidr); 160 } while (psysr & PSYSR_AFF_L0); 161 162 fvp_program_mailbox(mpidr, sec_entrypoint); 163 fvp_pwrc_write_pponr(mpidr); 164 165 return rc; 166 } 167 168 /******************************************************************************* 169 * FVP handler called when an affinity instance is about to be turned off. The 170 * level and mpidr determine the affinity instance. The 'state' arg. allows the 171 * platform to decide whether the cluster is being turned off and take apt 172 * actions. 173 * 174 * CAUTION: There is no guarantee that caches will remain turned on across calls 175 * to this function as each affinity level is dealt with. So do not write & read 176 * global variables across calls. It will be wise to do flush a write to the 177 * global to prevent unpredictable results. 178 ******************************************************************************/ 179 void fvp_affinst_off(unsigned int afflvl, 180 unsigned int state) 181 { 182 /* Determine if any platform actions need to be executed */ 183 if (fvp_do_plat_actions(afflvl, state) == -EAGAIN) 184 return; 185 186 /* 187 * If execution reaches this stage then this affinity level will be 188 * suspended. Perform at least the cpu specific actions followed the 189 * cluster specific operations if applicable. 190 */ 191 fvp_cpu_pwrdwn_common(); 192 193 if (afflvl != MPIDR_AFFLVL0) 194 fvp_cluster_pwrdwn_common(); 195 196 } 197 198 /******************************************************************************* 199 * FVP handler called when an affinity instance is about to be suspended. The 200 * level and mpidr determine the affinity instance. The 'state' arg. allows the 201 * platform to decide whether the cluster is being turned off and take apt 202 * actions. 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 ******************************************************************************/ 209 void fvp_affinst_suspend(unsigned long sec_entrypoint, 210 unsigned int afflvl, 211 unsigned int state) 212 { 213 unsigned long mpidr; 214 215 /* Determine if any platform actions need to be executed. */ 216 if (fvp_do_plat_actions(afflvl, state) == -EAGAIN) 217 return; 218 219 /* Get the mpidr for this cpu */ 220 mpidr = read_mpidr_el1(); 221 222 /* Program the jump address for the this cpu */ 223 fvp_program_mailbox(mpidr, sec_entrypoint); 224 225 /* Program the power controller to enable wakeup interrupts. */ 226 fvp_pwrc_set_wen(mpidr); 227 228 /* Perform the common cpu specific operations */ 229 fvp_cpu_pwrdwn_common(); 230 231 /* Perform the common cluster specific operations */ 232 if (afflvl != MPIDR_AFFLVL0) 233 fvp_cluster_pwrdwn_common(); 234 } 235 236 /******************************************************************************* 237 * FVP handler called when an affinity instance has just been powered on after 238 * being turned off earlier. The level and mpidr determine the affinity 239 * instance. The 'state' arg. allows the platform to decide whether the cluster 240 * was turned off prior to wakeup and do what's necessary to setup it up 241 * correctly. 242 ******************************************************************************/ 243 void fvp_affinst_on_finish(unsigned int afflvl, 244 unsigned int state) 245 { 246 unsigned long mpidr; 247 248 /* Determine if any platform actions need to be executed. */ 249 if (fvp_do_plat_actions(afflvl, state) == -EAGAIN) 250 return; 251 252 /* Get the mpidr for this cpu */ 253 mpidr = read_mpidr_el1(); 254 255 /* Perform the common cluster specific operations */ 256 if (afflvl != MPIDR_AFFLVL0) { 257 /* 258 * This CPU might have woken up whilst the cluster was 259 * attempting to power down. In this case the FVP power 260 * controller will have a pending cluster power off request 261 * which needs to be cleared by writing to the PPONR register. 262 * This prevents the power controller from interpreting a 263 * subsequent entry of this cpu into a simple wfi as a power 264 * down request. 265 */ 266 fvp_pwrc_write_pponr(mpidr); 267 268 /* Enable coherency if this cluster was off */ 269 fvp_cci_enable(); 270 } 271 272 /* 273 * Clear PWKUPR.WEN bit to ensure interrupts do not interfere 274 * with a cpu power down unless the bit is set again 275 */ 276 fvp_pwrc_clr_wen(mpidr); 277 278 /* Zero the jump address in the mailbox for this cpu */ 279 fvp_program_mailbox(mpidr, 0); 280 281 /* Enable the gic cpu interface */ 282 arm_gic_cpuif_setup(); 283 284 /* TODO: This setup is needed only after a cold boot */ 285 arm_gic_pcpu_distif_setup(); 286 } 287 288 /******************************************************************************* 289 * FVP handler called when an affinity instance has just been powered on after 290 * having been suspended earlier. The level and mpidr determine the affinity 291 * instance. 292 * TODO: At the moment we reuse the on finisher and reinitialize the secure 293 * context. Need to implement a separate suspend finisher. 294 ******************************************************************************/ 295 void fvp_affinst_suspend_finish(unsigned int afflvl, 296 unsigned int state) 297 { 298 fvp_affinst_on_finish(afflvl, state); 299 } 300 301 /******************************************************************************* 302 * FVP handlers to shutdown/reboot the system 303 ******************************************************************************/ 304 static void __dead2 fvp_system_off(void) 305 { 306 /* Write the System Configuration Control Register */ 307 mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGCTRL, 308 CFGCTRL_START | CFGCTRL_RW | CFGCTRL_FUNC(FUNC_SHUTDOWN)); 309 wfi(); 310 ERROR("FVP System Off: operation not handled.\n"); 311 panic(); 312 } 313 314 static void __dead2 fvp_system_reset(void) 315 { 316 /* Write the System Configuration Control Register */ 317 mmio_write_32(VE_SYSREGS_BASE + V2M_SYS_CFGCTRL, 318 CFGCTRL_START | CFGCTRL_RW | CFGCTRL_FUNC(FUNC_REBOOT)); 319 wfi(); 320 ERROR("FVP System Reset: operation not handled.\n"); 321 panic(); 322 } 323 324 /******************************************************************************* 325 * FVP handler called to check the validity of the power state parameter. 326 ******************************************************************************/ 327 int fvp_validate_power_state(unsigned int power_state) 328 { 329 /* Sanity check the requested state */ 330 if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) { 331 /* 332 * It's possible to enter standby only on affinity level 0 333 * i.e. a cpu on the fvp. Ignore any other affinity level. 334 */ 335 if (psci_get_pstate_afflvl(power_state) != MPIDR_AFFLVL0) 336 return PSCI_E_INVALID_PARAMS; 337 } 338 339 /* 340 * We expect the 'state id' to be zero. 341 */ 342 if (psci_get_pstate_id(power_state)) 343 return PSCI_E_INVALID_PARAMS; 344 345 return PSCI_E_SUCCESS; 346 } 347 348 /******************************************************************************* 349 * Export the platform handlers to enable psci to invoke them 350 ******************************************************************************/ 351 static const plat_pm_ops_t fvp_plat_pm_ops = { 352 .affinst_standby = fvp_affinst_standby, 353 .affinst_on = fvp_affinst_on, 354 .affinst_off = fvp_affinst_off, 355 .affinst_suspend = fvp_affinst_suspend, 356 .affinst_on_finish = fvp_affinst_on_finish, 357 .affinst_suspend_finish = fvp_affinst_suspend_finish, 358 .system_off = fvp_system_off, 359 .system_reset = fvp_system_reset, 360 .validate_power_state = fvp_validate_power_state 361 }; 362 363 /******************************************************************************* 364 * Export the platform specific power ops & initialize the fvp power controller 365 ******************************************************************************/ 366 int platform_setup_pm(const plat_pm_ops_t **plat_ops) 367 { 368 *plat_ops = &fvp_plat_pm_ops; 369 return 0; 370 } 371