1// reset-pso.S -- PSO restore routine, invoked from Reset Vector 2// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/core-shutoff.S#1 $ 3 4// Copyright (c) 2012-2013 Tensilica Inc. 5// 6// Permission is hereby granted, free of charge, to any person obtaining 7// a copy of this software and associated documentation files (the 8// "Software"), to deal in the Software without restriction, including 9// without limitation the rights to use, copy, modify, merge, publish, 10// distribute, sublicense, and/or sell copies of the Software, and to 11// permit persons to whom the Software is furnished to do so, subject to 12// the following conditions: 13// 14// The above copyright notice and this permission notice shall be included 15// in all copies or substantial portions of the Software. 16// 17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25#include <xtensa/coreasm.h> 26#include <xtensa/corebits.h> 27#include <xtensa/cacheasm.h> 28#include <xtensa/cacheattrasm.h> 29#include <xtensa/xdm-regs.h> 30#include <xtensa/xtruntime-core-state.h> 31#include "xtos-internal.h" 32 33#if XCHAL_HAVE_PSO 34 .macro simulate_reset 35 // Single or multiple power domains, no retention. 36 // Just simulate reset. Set PS: 37 movi a5, 0x1F 38 wsr.ps a5 39 rsync 40 // Scramble things: 41 rotw 3 42 // Jump to reset vector: 43 movi a5, _ResetVector 44 jx a5 45 .endm 46#endif 47 48 49#if XCHAL_HAVE_PSO_CDM && ! XCHAL_HAVE_PSO_FULL_RETENTION 50 // PSO: core state save area. 51 // This could be pretty large (includes TIE state, TLB state, many regs). 52 // 53 .section .bss, "aw" 54 .align XCHAL_TOTAL_SA_ALIGN 55 .global _xtos_pso_savearea 56 .type _xtos_pso_savearea, @object 57 .size _xtos_pso_savearea, XtosCoreStateSize 58_xtos_pso_savearea: 59 .space XtosCoreStateSize 60#endif 61 62 63 .text 64 65 66 // This version of the _xtos_core_shutoff() function can be called from assembly-level, 67 // where the stack might not be defined/usable, so can't do window-spill 68 // etc. This saves address registers per call0 ABI (all except a0/a2..a11). 69 // 70 // On entry: a0 = return PC, a2 = flags argument, a3..a11 = undefined/available. 71 // All other registers are saved/restored. 72 // 73 .align 4 74 .global _xtos_core_shutoff_nw 75 .type _xtos_core_shutoff_nw,@function 76_xtos_core_shutoff_nw: 77#if XCHAL_HAVE_PSO_CDM && ! XCHAL_HAVE_PSO_FULL_RETENTION 78 movi a5, _xtos_core_save_nw 79#endif 80 mov a11, a0 // ABI-independent return PC 81 j .Lcommon_shutoff 82 .size _xtos_core_shutoff_nw, . - _xtos_core_shutoff_nw 83 84 85 86 // int _xtos_core_shutoff(unsigned flags) 87 // 88 // Save all processor state and shut-off the core. 89 // Returns when the core wakes up, and all state was restored 90 // (except in single power domain case, see below). 91 // 92 // For more details see: System SW Ref Manual, XTOS Chapter. 93 // 94 // Possible return values: 95 // 96 // 0 core did shut-off (return via reset vector, 97 // or after waiti for full-retention case) 98 // 99 // 1,2 core did not shut-off (other requestors were already 100 // requesting this core to stay on at time of call) 101 // (1 == early, 2 == late) 102 // 103 // 3 core did not shut-off (multi-power-domains no retention, 104 // and waiti resumed; FIXME: can this happen?) 105 // 106 // -1 core does not have PSO feature 107 // 108 // NOTE: in the single power domain case, this function never returns. 109 // The external system must power the core off than back on, 110 // and execution resumes at the reset vector. 111 // 112 // The flags parameter indicates whether to request memory and/or debug domains 113 // to stay powered on while the core is shut-off. (This parameter is ignored 114 // for the single power domain case.) If 0, they are both allowed to 115 // shut-off (although other external requesters may keep them powered on). 116 // Otherwise, one or both of these bits may be specified (or'ed together): 117 // XTOS_KEEPON_MEM force memory domain on during core power shut-off 118 // XTOS_KEEPON_DEBUG force debug domain on during core power shut-off 119 // If XTOS_KEEPON_MEM is specified, dcache writeback is NOT done. 120 // 121 // Effectively, the flags parameter sets the value of these two PWRCTL register 122 // bits (over ERI) during core power shut-off. The value of these two bits 123 // (as they were prior to calling this function) are saved, and restored on wakeup. 124 // Thus, if the core was requesting that the debug domain be powered on, and 125 // _xtos_core_shutoff() lets it power-off, then upon wakeup, the software restore 126 // sequence restores debug domain power, and waits for debug power to be ON. 127 // 128 // 129 .align 4 130 .global _xtos_core_shutoff 131 .type _xtos_core_shutoff,@function 132_xtos_core_shutoff: 133 abi_entry 134 135#if XCHAL_HAVE_PSO_CDM && ! XCHAL_HAVE_PSO_FULL_RETENTION 136 movi a5, _xtos_core_save_entry 137#endif 138 movi a11, 1f // ABI-independent return PC 139 j .Lcommon_shutoff 140 1411: abi_return 142 143 144 145 146 .align 4 147.Lcommon_shutoff: 148 149 150 151#if XCHAL_HAVE_PSO_CDM && XCHAL_HAVE_PSO_FULL_RETENTION 152 // Multiple power domains, full retention in HW. 153 // Do the minimum required (things that need to be changed during shutoff): 154 155 // Check whether other agents are keeping this core powered on, 156 // and avoid going through save sequence if we're not going to 157 // power down anyway. 158 movi a3, XDM_MISC_PWRSTAT 159 rer a6, a3 160 movi a5, 1 // indicates other agents want this core powered on 161 bbsi.l a6, PWRSTAT_CORE_STILL_NEEDED_SHIFT, 1f 162 163 rsil a8, 15 // disable interrupts 164 165# if XCHAL_HAVE_PREFETCH 166 // Save prefetch control and disable prefetch. 167 movi a10, 0 168 xsr.prefctl a10 169# endif 170 171# if XCHAL_DCACHE_IS_WRITEBACK 172 bbsi.l a2, PWRCTL_MEM_WAKEUP_SHIFT, 7f // letting caches power off? 173 dcache_writeback_all a4, a7, a9,0 // yes: writeback 174 memw // wait for writeback to complete 1757: 176# endif 177 178 // Save PWRCTL, and set ShutProcOffOnPWait (for WAITI to shut-off the core). 179 // (With dcache coherence, can this be used as signal to system 180 // to turn off snoops to this core?) 181 // 182 movi a4, XDM_MISC_PWRCTL 183 rer a9, a4 // get pwrctl 184 movi a6, PWRCTL_CORE_SHUTOFF // aka ShutProcOffOnPWait 185 or a7, a9, a6 // indicate WAITI will shut-off 186 xor a9, a7, a6 // make sure it's clear in saved pwrctl 187 wer a7, a4 // write new pwrctl 188 189 // Make sure everything stabilizes: 190 isync 191 extw 192 193 // With ShutProcOffOnPWait set, external agents can't change their mind. 194 // So check again whether other agents are keeping this core powered on, 195 // and avoid going through save sequence if we're not going to 196 // power down anyway. 197 rer a6, a3 // read PWRSTAT 198 movi a5, 2 // if abort: external agent wants core powered on 199 bbsi.l a6, PWRSTAT_CORE_STILL_NEEDED_SHIFT, .Lshutoff_late_abort 200 201 // Set PWRCTL MEM_WAKEUP bit according to flags (whether to let mem power off). 202 movi a6, PWRCTL_MEM_WAKEUP 203 or a5, a7, a6 // set... 204 xor a5, a5, a6 // ... and clear MEM_WAKEUP bit to write 205 and a6, a2, a6 // isolate MEM_WAKEUP bit from flags 206 or a5, a5, a6 // set MEM_WAKEUP bit to write from flags 207 // Clear PWRCTL DEBUG_WAKEUP bit if cleared in flags (if letting debug power off). 208 movi a6, ~PWRCTL_DEBUG_WAKEUP 209 or a6, a2, a6 // isolate DEBUG_WAKEUP bit from flags 210 and a6, a5, a6 // clear it if was clear in flags 211 // Update PWRCTL 212 wer a6, a4 // write new pwrctl 213 extw // let the new pwrctl value settle 214 215 // Okay, go for it -- power down (shutoff). 216 217# if !XTOS_PSO_TEST 218 waiti 0 // now shut-off! (interrupts enabled for power-on) 219# endif 220 // Resumes here after power comes back on, after some interrupt taken. 221 wsr.ps a8 // restore interrupts 222 movi a5, 0 // successful 223 rsync // ensure wsr.ps completes 224 225 // FIXME: do we need to initialize caches? 226 227.Lshutoff_late_abort: 228 wer a7, a4 // restore pwrctl (except ShutProcOffOnPWait still set) 229 230 // Wait for debug powerup to complete (if started): 231 bbci.l a7, PWRCTL_DEBUG_WAKEUP_SHIFT, 3f 232 movi a6, XDM_MISC_PWRSTAT 2332: rer a6, a6 // read PWRSTAT 234 bbci.l a6, PWRSTAT_DEBUG_DOMAIN_ON_SHIFT, 2b // loop until powered up 2353: 236 237# if XCHAL_HAVE_PREFETCH 238 wsr.prefctl a10 // restore prefetch control 239# endif 240 241 // If CachesLostPower bit set, is there need to initialize caches? 242 243 wer a9, a4 // clear ShutProcOffOnPWait 244 245 wsr.ps a8 // restore interrupts 246 rsync // ensure wsr.ps completes 247 2481: mov a2, a5 249 jx a11 // return (to ABI-dependent code if C callable) 250 251 252 253#elif XCHAL_HAVE_PSO_CDM /*&& !XCHAL_HAVE_PSO_FULL_RETENTION*/ 254 // Multiple power domains, no hardware retention. 255 // Do full core state save/restore in software. 256 257 // Check whether other agents are keeping this core powered on, 258 // and avoid going through save sequence if we're not going to 259 // power down anyway. 260 movi a3, XDM_MISC_PWRSTAT 261 rer a3, a3 262 bbsi.l a3, PWRSTAT_CORE_STILL_NEEDED_SHIFT, 1f 263 264 movi a3, XTOS_COREF_PSO 265 or a2, a2, a3 // indicate power shutoff in flags 266 267 movi a3, _xtos_pso_savearea 268 movi a4, _xtos_core_shutoff_aftersave 269 jx a5 // continue in _xtos_core_save (past prologue) 270 // which saves processor state, powers down 271 // debug/mem per a2, shuts off prefetch and 272 // snooping, and jumps to a4 273 2741: movi a2, 1 // other agents want this core powered on 275 jx a11 // return (to ABI-dependent code if C callable) 276 277 .align 4 278 //.global _xtos_core_shutoff_aftersave 279_xtos_core_shutoff_aftersave: 280 281 // Multiple power domains, no retention. 282 283 // Set ShutProcOffOnPWait, for WAITI to shut-off the core. 284 // (With dcache coherence, can this be used as signal to system 285 // to turn off snoops to this core?) 286 // 287 movi a4, XDM_MISC_PWRCTL 288 rer a7, a4 // get pwrctl 289 movi a6, PWRCTL_CORE_SHUTOFF // aka ShutProcOffOnPWait 290 or a7, a7, a6 // indicate WAITI will shut-off 291 wer a7, a4 // write new pwrctl 292 293 // Make sure everything stabilizes: 294 isync 295 extw 296 297 // Check whether other agents are keeping this core powered on, 298 // and avoid going through save sequence if we're not going to 299 // power down anyway. 300 movi a4, XDM_MISC_PWRSTAT 301 movi a2, 2 // if abort: external agent wants core powered on 302 rer a6, a4 303 bbsi.l a6, PWRSTAT_CORE_STILL_NEEDED_SHIFT, .Lshutoff_late_abort 304 305 // Call system-specific function to wait for system specific 306 // transactions to quiesce before shutting down the processor. 307 // This function may also abort the shutdown, however whoever 308 // attempts it must do it carefully: the function must know 309 // that it's possible to abort, it must do whatever's needed 310 // in the system to resume normal execution (e.g. restart 311 // snoops, DMA, etc), and for power reasons the software must 312 // avoid calling this shutdown routine in the first place if 313 // it can know then that it would end up aborting here. 314 // 315 // This is always a call0 function. 316 // TBD: can it be a C function instead? 317 // TBD: describe exact calling conventions, if asm call0 318 319 .weak xtos_system_ready_for_core_shutoff 320 movi a2, xtos_system_ready_for_core_shutoff 321 //isync 322 beqz a2, 1f 323 callx0 a2 324 bnez a2, .Lshutoff_late_abort // if function returns error, abort shutdown 3251: 326 327 // Okay, go for it -- power down (shutoff). 328 329 330# if XTOS_PSO_TEST 331 // Test only -- weakly simulate shutoff in sw, don't actually do it. 332 simulate_reset 333# elif XCHAL_HAVE_INTERRUPTS 334 waiti 15 // now shut-off! 335# elif XCHAL_HAVE_HALT 336 halt 337# else 338# error "PSO assumes interrupts (for WAITI) or HALT architecture (for HALT)" 339# endif 340 341 // Execution should not proceed here. 342 // If we get here, some error has occurred [FIXME] 343 344 movi a2, 3 // WAITI resumed 345 346.Lshutoff_late_abort: 347 // We end up here if returning from shutoff request. 348 // Here, a2 == return code. 349 // Restore what's been clobbered (and doesn't get restored by caller): 350 // PWRCTL, MEMCTL, return PC. 351 352 l32i a0, a3, CS_SA_restore_label // restore return PC 353 354 // Restore PWRCTL. 355 movi a4, XDM_MISC_PWRCTL 356 l32i a5, a3, CS_SA_pwrctl // get saved pwrctl 357 wer a5, a4 // restore pwrctl 358 // Wait for debug powerup to complete (if started): 359 bbci.l a5, PWRCTL_DEBUG_WAKEUP_SHIFT, 1f 360 movi a7, XDM_MISC_PWRSTAT 3612: rer a6, a7 // read PWRSTAT 362 bbci.l a6, PWRSTAT_DEBUG_DOMAIN_ON_SHIFT, 2b // loop until powered up 3631: 364 365 // Restore MEMCTL. 366# if XCHAL_USE_MEMCTL 367 l32i a5, a3, CS_SA_memctl 368 wsr.memctl a5 369# endif 370 371 // Clear the signature, to mark save area as no longer valid. 372 s32i a2, a3, CS_SA_signature 373# if XCHAL_DCACHE_IS_WRITEBACK 374 dhwb a3, CS_SA_signature 375# endif 376 377 ret // return from _xtos_core_save_common 378 379 380 381#elif XCHAL_HAVE_PSO 382 // Single power domain. (No retention.) 383 384 rsil a8, 15 // disable interrupts 385 386# if XCHAL_HAVE_PREFETCH 387 // Disable prefetch. 388 movi a10, 0 389 wsr.memctl a10 390# endif 391 392# if XCHAL_DCACHE_IS_WRITEBACK 393 bbsi.l a2, PWRCTL_MEM_WAKEUP_SHIFT, 7f // letting caches power off? 394 dcache_writeback_all a4, a5, a6, 0 // yes: writeback 395 memw // wait for writeback to complete 3967: 397# endif 398 3991: waiti 15 // wait for shut-off 400 j 1b // loop until we get powered off 401 402 403 404#else 405 // No PSO. 406 movi a2, -1 407 jx a11 // return (to ABI-dependent code if C callable) 408 409#endif 410 411 412 413 414#if XCHAL_HAVE_PSO_CDM 415# if XCHAL_HAVE_PSO_FULL_RETENTION 416 417# else /* not full retention */ 418 419 420# endif /* !retention */ 421#endif /* multi power domains */ 422 423 424 .size _xtos_core_shutoff, . - _xtos_core_shutoff 425 426