linux/arch/arm/mach-omap2/sleep44xx.S
<<
>>
Prefs
   1/*
   2 * OMAP44xx sleep code.
   3 *
   4 * Copyright (C) 2011 Texas Instruments, Inc.
   5 *      Santosh Shilimkar <santosh.shilimkar@ti.com>
   6 *
   7 * This program is free software,you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 */
  11
  12#include <linux/linkage.h>
  13#include <asm/smp_scu.h>
  14#include <asm/memory.h>
  15#include <asm/hardware/cache-l2x0.h>
  16
  17#include "omap-secure.h"
  18
  19#include "common.h"
  20#include "omap44xx.h"
  21#include "omap4-sar-layout.h"
  22
  23#if defined(CONFIG_SMP) && defined(CONFIG_PM)
  24
  25.macro  DO_SMC
  26        dsb
  27        smc     #0
  28        dsb
  29.endm
  30
  31ppa_zero_params:
  32        .word           0x0
  33
  34ppa_por_params:
  35        .word           1, 0
  36
  37#ifdef CONFIG_ARCH_OMAP4
  38
  39/*
  40 * =============================
  41 * == CPU suspend finisher ==
  42 * =============================
  43 *
  44 * void omap4_finish_suspend(unsigned long cpu_state)
  45 *
  46 * This function code saves the CPU context and performs the CPU
  47 * power down sequence. Calling WFI effectively changes the CPU
  48 * power domains states to the desired target power state.
  49 *
  50 * @cpu_state : contains context save state (r0)
  51 *      0 - No context lost
  52 *      1 - CPUx L1 and logic lost: MPUSS CSWR
  53 *      2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR
  54 *      3 - CPUx L1 and logic lost + GIC + L2 lost: MPUSS OFF
  55 * @return: This function never returns for CPU OFF and DORMANT power states.
  56 * Post WFI, CPU transitions to DORMANT or OFF power state and on wake-up
  57 * from this follows a full CPU reset path via ROM code to CPU restore code.
  58 * The restore function pointer is stored at CPUx_WAKEUP_NS_PA_ADDR_OFFSET.
  59 * It returns to the caller for CPU INACTIVE and ON power states or in case
  60 * CPU failed to transition to targeted OFF/DORMANT state.
  61 *
  62 * omap4_finish_suspend() calls v7_flush_dcache_all() which doesn't save
  63 * stack frame and it expects the caller to take care of it. Hence the entire
  64 * stack frame is saved to avoid possible stack corruption.
  65 */
  66ENTRY(omap4_finish_suspend)
  67        stmfd   sp!, {r4-r12, lr}
  68        cmp     r0, #0x0
  69        beq     do_WFI                          @ No lowpower state, jump to WFI
  70
  71        /*
  72         * Flush all data from the L1 data cache before disabling
  73         * SCTLR.C bit.
  74         */
  75        bl      omap4_get_sar_ram_base
  76        ldr     r9, [r0, #OMAP_TYPE_OFFSET]
  77        cmp     r9, #0x1                        @ Check for HS device
  78        bne     skip_secure_l1_clean
  79        mov     r0, #SCU_PM_NORMAL
  80        mov     r1, #0xFF                       @ clean seucre L1
  81        stmfd   r13!, {r4-r12, r14}
  82        ldr     r12, =OMAP4_MON_SCU_PWR_INDEX
  83        DO_SMC
  84        ldmfd   r13!, {r4-r12, r14}
  85skip_secure_l1_clean:
  86        bl      v7_flush_dcache_all
  87
  88        /*
  89         * Clear the SCTLR.C bit to prevent further data cache
  90         * allocation. Clearing SCTLR.C would make all the data accesses
  91         * strongly ordered and would not hit the cache.
  92         */
  93        mrc     p15, 0, r0, c1, c0, 0
  94        bic     r0, r0, #(1 << 2)               @ Disable the C bit
  95        mcr     p15, 0, r0, c1, c0, 0
  96        isb
  97
  98        /*
  99         * Invalidate L1 data cache. Even though only invalidate is
 100         * necessary exported flush API is used here. Doing clean
 101         * on already clean cache would be almost NOP.
 102         */
 103        bl      v7_flush_dcache_all
 104
 105        /*
 106         * Switch the CPU from Symmetric Multiprocessing (SMP) mode
 107         * to AsymmetricMultiprocessing (AMP) mode by programming
 108         * the SCU power status to DORMANT or OFF mode.
 109         * This enables the CPU to be taken out of coherency by
 110         * preventing the CPU from receiving cache, TLB, or BTB
 111         * maintenance operations broadcast by other CPUs in the cluster.
 112         */
 113        bl      omap4_get_sar_ram_base
 114        mov     r8, r0
 115        ldr     r9, [r8, #OMAP_TYPE_OFFSET]
 116        cmp     r9, #0x1                        @ Check for HS device
 117        bne     scu_gp_set
 118        mrc     p15, 0, r0, c0, c0, 5           @ Read MPIDR
 119        ands    r0, r0, #0x0f
 120        ldreq   r0, [r8, #SCU_OFFSET0]
 121        ldrne   r0, [r8, #SCU_OFFSET1]
 122        mov     r1, #0x00
 123        stmfd   r13!, {r4-r12, r14}
 124        ldr     r12, =OMAP4_MON_SCU_PWR_INDEX
 125        DO_SMC
 126        ldmfd   r13!, {r4-r12, r14}
 127        b       skip_scu_gp_set
 128scu_gp_set:
 129        mrc     p15, 0, r0, c0, c0, 5           @ Read MPIDR
 130        ands    r0, r0, #0x0f
 131        ldreq   r1, [r8, #SCU_OFFSET0]
 132        ldrne   r1, [r8, #SCU_OFFSET1]
 133        bl      omap4_get_scu_base
 134        bl      scu_power_mode
 135skip_scu_gp_set:
 136        mrc     p15, 0, r0, c1, c1, 2           @ Read NSACR data
 137        tst     r0, #(1 << 18)
 138        mrcne   p15, 0, r0, c1, c0, 1
 139        bicne   r0, r0, #(1 << 6)               @ Disable SMP bit
 140        mcrne   p15, 0, r0, c1, c0, 1
 141        isb
 142        dsb
 143#ifdef CONFIG_CACHE_L2X0
 144        /*
 145         * Clean and invalidate the L2 cache.
 146         * Common cache-l2x0.c functions can't be used here since it
 147         * uses spinlocks. We are out of coherency here with data cache
 148         * disabled. The spinlock implementation uses exclusive load/store
 149         * instruction which can fail without data cache being enabled.
 150         * OMAP4 hardware doesn't support exclusive monitor which can
 151         * overcome exclusive access issue. Because of this, CPU can
 152         * lead to deadlock.
 153         */
 154        bl      omap4_get_sar_ram_base
 155        mov     r8, r0
 156        mrc     p15, 0, r5, c0, c0, 5           @ Read MPIDR
 157        ands    r5, r5, #0x0f
 158        ldreq   r0, [r8, #L2X0_SAVE_OFFSET0]    @ Retrieve L2 state from SAR
 159        ldrne   r0, [r8, #L2X0_SAVE_OFFSET1]    @ memory.
 160        cmp     r0, #3
 161        bne     do_WFI
 162#ifdef CONFIG_PL310_ERRATA_727915
 163        mov     r0, #0x03
 164        mov     r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
 165        DO_SMC
 166#endif
 167        bl      omap4_get_l2cache_base
 168        mov     r2, r0
 169        ldr     r0, =0xffff
 170        str     r0, [r2, #L2X0_CLEAN_INV_WAY]
 171wait:
 172        ldr     r0, [r2, #L2X0_CLEAN_INV_WAY]
 173        ldr     r1, =0xffff
 174        ands    r0, r0, r1
 175        bne     wait
 176#ifdef CONFIG_PL310_ERRATA_727915
 177        mov     r0, #0x00
 178        mov     r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
 179        DO_SMC
 180#endif
 181l2x_sync:
 182        bl      omap4_get_l2cache_base
 183        mov     r2, r0
 184        mov     r0, #0x0
 185        str     r0, [r2, #L2X0_CACHE_SYNC]
 186sync:
 187        ldr     r0, [r2, #L2X0_CACHE_SYNC]
 188        ands    r0, r0, #0x1
 189        bne     sync
 190#endif
 191
 192do_WFI:
 193        bl      omap_do_wfi
 194
 195        /*
 196         * CPU is here when it failed to enter OFF/DORMANT or
 197         * no low power state was attempted.
 198         */
 199        mrc     p15, 0, r0, c1, c0, 0
 200        tst     r0, #(1 << 2)                   @ Check C bit enabled?
 201        orreq   r0, r0, #(1 << 2)               @ Enable the C bit
 202        mcreq   p15, 0, r0, c1, c0, 0
 203        isb
 204
 205        /*
 206         * Ensure the CPU power state is set to NORMAL in
 207         * SCU power state so that CPU is back in coherency.
 208         * In non-coherent mode CPU can lock-up and lead to
 209         * system deadlock.
 210         */
 211        mrc     p15, 0, r0, c1, c0, 1
 212        tst     r0, #(1 << 6)                   @ Check SMP bit enabled?
 213        orreq   r0, r0, #(1 << 6)
 214        mcreq   p15, 0, r0, c1, c0, 1
 215        isb
 216        bl      omap4_get_sar_ram_base
 217        mov     r8, r0
 218        ldr     r9, [r8, #OMAP_TYPE_OFFSET]
 219        cmp     r9, #0x1                        @ Check for HS device
 220        bne     scu_gp_clear
 221        mov     r0, #SCU_PM_NORMAL
 222        mov     r1, #0x00
 223        stmfd   r13!, {r4-r12, r14}
 224        ldr     r12, =OMAP4_MON_SCU_PWR_INDEX
 225        DO_SMC
 226        ldmfd   r13!, {r4-r12, r14}
 227        b       skip_scu_gp_clear
 228scu_gp_clear:
 229        bl      omap4_get_scu_base
 230        mov     r1, #SCU_PM_NORMAL
 231        bl      scu_power_mode
 232skip_scu_gp_clear:
 233        isb
 234        dsb
 235        ldmfd   sp!, {r4-r12, pc}
 236ENDPROC(omap4_finish_suspend)
 237
 238/*
 239 * ============================
 240 * == CPU resume entry point ==
 241 * ============================
 242 *
 243 * void omap4_cpu_resume(void)
 244 *
 245 * ROM code jumps to this function while waking up from CPU
 246 * OFF or DORMANT state. Physical address of the function is
 247 * stored in the SAR RAM while entering to OFF or DORMANT mode.
 248 * The restore function pointer is stored at CPUx_WAKEUP_NS_PA_ADDR_OFFSET.
 249 */
 250ENTRY(omap4_cpu_resume)
 251        /*
 252         * Configure ACTRL and enable NS SMP bit access on CPU1 on HS device.
 253         * OMAP44XX EMU/HS devices - CPU0 SMP bit access is enabled in PPA
 254         * init and for CPU1, a secure PPA API provided. CPU0 must be ON
 255         * while executing NS_SMP API on CPU1 and PPA version must be 1.4.0+.
 256         * OMAP443X GP devices- SMP bit isn't accessible.
 257         * OMAP446X GP devices - SMP bit access is enabled on both CPUs.
 258         */
 259        ldr     r8, =OMAP44XX_SAR_RAM_BASE
 260        ldr     r9, [r8, #OMAP_TYPE_OFFSET]
 261        cmp     r9, #0x1                        @ Skip if GP device
 262        bne     skip_ns_smp_enable
 263        mrc     p15, 0, r0, c0, c0, 5
 264        ands    r0, r0, #0x0f
 265        beq     skip_ns_smp_enable
 266ppa_actrl_retry:
 267        mov     r0, #OMAP4_PPA_CPU_ACTRL_SMP_INDEX
 268        adr     r3, ppa_zero_params             @ Pointer to parameters
 269        mov     r1, #0x0                        @ Process ID
 270        mov     r2, #0x4                        @ Flag
 271        mov     r6, #0xff
 272        mov     r12, #0x00                      @ Secure Service ID
 273        DO_SMC
 274        cmp     r0, #0x0                        @ API returns 0 on success.
 275        beq     enable_smp_bit
 276        b       ppa_actrl_retry
 277enable_smp_bit:
 278        mrc     p15, 0, r0, c1, c0, 1
 279        tst     r0, #(1 << 6)                   @ Check SMP bit enabled?
 280        orreq   r0, r0, #(1 << 6)
 281        mcreq   p15, 0, r0, c1, c0, 1
 282        isb
 283skip_ns_smp_enable:
 284#ifdef CONFIG_CACHE_L2X0
 285        /*
 286         * Restore the L2 AUXCTRL and enable the L2 cache.
 287         * OMAP4_MON_L2X0_AUXCTRL_INDEX =  Program the L2X0 AUXCTRL
 288         * OMAP4_MON_L2X0_CTRL_INDEX =  Enable the L2 using L2X0 CTRL
 289         * register r0 contains value to be programmed.
 290         * L2 cache is already invalidate by ROM code as part
 291         * of MPUSS OFF wakeup path.
 292         */
 293        ldr     r2, =OMAP44XX_L2CACHE_BASE
 294        ldr     r0, [r2, #L2X0_CTRL]
 295        and     r0, #0x0f
 296        cmp     r0, #1
 297        beq     skip_l2en                       @ Skip if already enabled
 298        ldr     r3, =OMAP44XX_SAR_RAM_BASE
 299        ldr     r1, [r3, #OMAP_TYPE_OFFSET]
 300        cmp     r1, #0x1                        @ Check for HS device
 301        bne     set_gp_por
 302        ldr     r0, =OMAP4_PPA_L2_POR_INDEX
 303        ldr     r1, =OMAP44XX_SAR_RAM_BASE
 304        ldr     r4, [r1, #L2X0_PREFETCH_CTRL_OFFSET]
 305        adr     r3, ppa_por_params
 306        str     r4, [r3, #0x04]
 307        mov     r1, #0x0                        @ Process ID
 308        mov     r2, #0x4                        @ Flag
 309        mov     r6, #0xff
 310        mov     r12, #0x00                      @ Secure Service ID
 311        DO_SMC
 312        b       set_aux_ctrl
 313set_gp_por:
 314        ldr     r1, =OMAP44XX_SAR_RAM_BASE
 315        ldr     r0, [r1, #L2X0_PREFETCH_CTRL_OFFSET]
 316        ldr     r12, =OMAP4_MON_L2X0_PREFETCH_INDEX     @ Setup L2 PREFETCH
 317        DO_SMC
 318set_aux_ctrl:
 319        ldr     r1, =OMAP44XX_SAR_RAM_BASE
 320        ldr     r0, [r1, #L2X0_AUXCTRL_OFFSET]
 321        ldr     r12, =OMAP4_MON_L2X0_AUXCTRL_INDEX      @ Setup L2 AUXCTRL
 322        DO_SMC
 323        mov     r0, #0x1
 324        ldr     r12, =OMAP4_MON_L2X0_CTRL_INDEX         @ Enable L2 cache
 325        DO_SMC
 326skip_l2en:
 327#endif
 328
 329        b       cpu_resume                      @ Jump to generic resume
 330ENDPROC(omap4_cpu_resume)
 331#endif  /* CONFIG_ARCH_OMAP4 */
 332
 333#endif  /* defined(CONFIG_SMP) && defined(CONFIG_PM) */
 334
 335#ifndef CONFIG_OMAP4_ERRATA_I688
 336ENTRY(omap_bus_sync)
 337        mov     pc, lr
 338ENDPROC(omap_bus_sync)
 339#endif
 340
 341ENTRY(omap_do_wfi)
 342        stmfd   sp!, {lr}
 343        /* Drain interconnect write buffers. */
 344        bl omap_bus_sync
 345
 346        /*
 347         * Execute an ISB instruction to ensure that all of the
 348         * CP15 register changes have been committed.
 349         */
 350        isb
 351
 352        /*
 353         * Execute a barrier instruction to ensure that all cache,
 354         * TLB and branch predictor maintenance operations issued
 355         * by any CPU in the cluster have completed.
 356         */
 357        dsb
 358        dmb
 359
 360        /*
 361         * Execute a WFI instruction and wait until the
 362         * STANDBYWFI output is asserted to indicate that the
 363         * CPU is in idle and low power state. CPU can specualatively
 364         * prefetch the instructions so add NOPs after WFI. Sixteen
 365         * NOPs as per Cortex-A9 pipeline.
 366         */
 367        wfi                                     @ Wait For Interrupt
 368        nop
 369        nop
 370        nop
 371        nop
 372        nop
 373        nop
 374        nop
 375        nop
 376        nop
 377        nop
 378        nop
 379        nop
 380        nop
 381        nop
 382        nop
 383        nop
 384
 385        ldmfd   sp!, {pc}
 386ENDPROC(omap_do_wfi)
 387