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