linux/arch/arm/mach-tegra/sleep-tegra30.S
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms and conditions of the GNU General Public License,
   6 * version 2, as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope it will be useful, but WITHOUT
   9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  11 * more details.
  12 *
  13 * You should have received a copy of the GNU General Public License
  14 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  15 */
  16
  17#include <linux/linkage.h>
  18
  19#include <asm/assembler.h>
  20#include <asm/asm-offsets.h>
  21
  22#include "fuse.h"
  23#include "sleep.h"
  24#include "flowctrl.h"
  25
  26#define TEGRA30_POWER_HOTPLUG_SHUTDOWN  (1 << 27) /* Hotplug shutdown */
  27
  28#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
  29/*
  30 * tegra30_hotplug_shutdown(void)
  31 *
  32 * Powergates the current CPU.
  33 * Should never return.
  34 */
  35ENTRY(tegra30_hotplug_shutdown)
  36        /* Powergate this CPU */
  37        mov     r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
  38        bl      tegra30_cpu_shutdown
  39        mov     pc, lr                  @ should never get here
  40ENDPROC(tegra30_hotplug_shutdown)
  41
  42/*
  43 * tegra30_cpu_shutdown(unsigned long flags)
  44 *
  45 * Puts the current CPU in wait-for-event mode on the flow controller
  46 * and powergates it -- flags (in R0) indicate the request type.
  47 *
  48 * r10 = SoC ID
  49 * corrupts r0-r4, r10-r12
  50 */
  51ENTRY(tegra30_cpu_shutdown)
  52        cpu_id  r3
  53        tegra_get_soc_id TEGRA_APB_MISC_VIRT, r10
  54        cmp     r10, #TEGRA30
  55        bne     _no_cpu0_chk    @ It's not Tegra30
  56
  57        cmp     r3, #0
  58        moveq   pc, lr          @ Must never be called for CPU 0
  59_no_cpu0_chk:
  60
  61        ldr     r12, =TEGRA_FLOW_CTRL_VIRT
  62        cpu_to_csr_reg r1, r3
  63        add     r1, r1, r12     @ virtual CSR address for this CPU
  64        cpu_to_halt_reg r2, r3
  65        add     r2, r2, r12     @ virtual HALT_EVENTS address for this CPU
  66
  67        /*
  68         * Clear this CPU's "event" and "interrupt" flags and power gate
  69         * it when halting but not before it is in the "WFE" state.
  70         */
  71        movw    r12, \
  72                FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG | \
  73                FLOW_CTRL_CSR_ENABLE
  74        cmp     r10, #TEGRA30
  75        moveq   r4, #(1 << 4)                   @ wfe bitmap
  76        movne   r4, #(1 << 8)                   @ wfi bitmap
  77 ARM(   orr     r12, r12, r4, lsl r3    )
  78 THUMB( lsl     r4, r4, r3              )
  79 THUMB( orr     r12, r12, r4            )
  80        str     r12, [r1]
  81
  82        /* Halt this CPU. */
  83        mov     r3, #0x400
  84delay_1:
  85        subs    r3, r3, #1                      @ delay as a part of wfe war.
  86        bge     delay_1;
  87        cpsid   a                               @ disable imprecise aborts.
  88        ldr     r3, [r1]                        @ read CSR
  89        str     r3, [r1]                        @ clear CSR
  90
  91        tst     r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
  92        beq     flow_ctrl_setting_for_lp2
  93
  94        /* flow controller set up for hotplug */
  95        mov     r3, #FLOW_CTRL_WAITEVENT                @ For hotplug
  96        b       flow_ctrl_done
  97flow_ctrl_setting_for_lp2:
  98        /* flow controller set up for LP2 */
  99        cmp     r10, #TEGRA30
 100        moveq   r3, #FLOW_CTRL_WAIT_FOR_INTERRUPT       @ For LP2
 101        movne   r3, #FLOW_CTRL_WAITEVENT
 102flow_ctrl_done:
 103        cmp     r10, #TEGRA30
 104        str     r3, [r2]
 105        ldr     r0, [r2]
 106        b       wfe_war
 107
 108__cpu_reset_again:
 109        dsb
 110        .align 5
 111        wfeeq                                   @ CPU should be power gated here
 112        wfine
 113wfe_war:
 114        b       __cpu_reset_again
 115
 116        /*
 117         * 38 nop's, which fills reset of wfe cache line and
 118         * 4 more cachelines with nop
 119         */
 120        .rept 38
 121        nop
 122        .endr
 123        b       .                               @ should never get here
 124
 125ENDPROC(tegra30_cpu_shutdown)
 126#endif
 127
 128#ifdef CONFIG_PM_SLEEP
 129/*
 130 * tegra30_sleep_cpu_secondary_finish(unsigned long v2p)
 131 *
 132 * Enters LP2 on secondary CPU by exiting coherency and powergating the CPU.
 133 */
 134ENTRY(tegra30_sleep_cpu_secondary_finish)
 135        mov     r7, lr
 136
 137        /* Flush and disable the L1 data cache */
 138        bl      tegra_disable_clean_inv_dcache
 139
 140        /* Powergate this CPU. */
 141        mov     r0, #0                          @ power mode flags (!hotplug)
 142        bl      tegra30_cpu_shutdown
 143        mov     r0, #1                          @ never return here
 144        mov     pc, r7
 145ENDPROC(tegra30_sleep_cpu_secondary_finish)
 146
 147/*
 148 * tegra30_tear_down_cpu
 149 *
 150 * Switches the CPU to enter sleep.
 151 */
 152ENTRY(tegra30_tear_down_cpu)
 153        mov32   r6, TEGRA_FLOW_CTRL_BASE
 154
 155        b       tegra30_enter_sleep
 156ENDPROC(tegra30_tear_down_cpu)
 157
 158/*
 159 * tegra30_enter_sleep
 160 *
 161 * uses flow controller to enter sleep state
 162 * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
 163 * executes from SDRAM with target state is LP2
 164 * r6 = TEGRA_FLOW_CTRL_BASE
 165 */
 166tegra30_enter_sleep:
 167        cpu_id  r1
 168
 169        cpu_to_csr_reg  r2, r1
 170        ldr     r0, [r6, r2]
 171        orr     r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
 172        orr     r0, r0, #FLOW_CTRL_CSR_ENABLE
 173        str     r0, [r6, r2]
 174
 175        mov     r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
 176        orr     r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
 177        cpu_to_halt_reg r2, r1
 178        str     r0, [r6, r2]
 179        dsb
 180        ldr     r0, [r6, r2] /* memory barrier */
 181
 182halted:
 183        isb
 184        dsb
 185        wfi     /* CPU should be power gated here */
 186
 187        /* !!!FIXME!!! Implement halt failure handler */
 188        b       halted
 189
 190#endif
 191