1/* 2 * arch/arm/mach-tegra/sleep.S 3 * 4 * Copyright (c) 2010-2011, NVIDIA Corporation. 5 * Copyright (c) 2011, Google, Inc. 6 * 7 * Author: Colin Cross <ccross@android.com> 8 * Gary King <gking@nvidia.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, but WITHOUT 16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 18 * more details. 19 * 20 * You should have received a copy of the GNU General Public License along 21 * with this program; if not, write to the Free Software Foundation, Inc., 22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 23 */ 24 25#include <linux/linkage.h> 26 27#include <asm/assembler.h> 28 29#include <mach/iomap.h> 30 31#include "flowctrl.h" 32 33#define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \ 34 + IO_PPSB_VIRT) 35 36/* returns the offset of the flow controller halt register for a cpu */ 37.macro cpu_to_halt_reg rd, rcpu 38 cmp \rcpu, #0 39 subne \rd, \rcpu, #1 40 movne \rd, \rd, lsl #3 41 addne \rd, \rd, #0x14 42 moveq \rd, #0 43.endm 44 45/* returns the offset of the flow controller csr register for a cpu */ 46.macro cpu_to_csr_reg rd, rcpu 47 cmp \rcpu, #0 48 subne \rd, \rcpu, #1 49 movne \rd, \rd, lsl #3 50 addne \rd, \rd, #0x18 51 moveq \rd, #8 52.endm 53 54/* returns the ID of the current processor */ 55.macro cpu_id, rd 56 mrc p15, 0, \rd, c0, c0, 5 57 and \rd, \rd, #0xF 58.endm 59 60/* loads a 32-bit value into a register without a data access */ 61.macro mov32, reg, val 62 movw \reg, #:lower16:\val 63 movt \reg, #:upper16:\val 64.endm 65 66/* 67 * tegra_cpu_wfi 68 * 69 * puts current CPU in clock-gated wfi using the flow controller 70 * 71 * corrupts r0-r3 72 * must be called with MMU on 73 */ 74 75ENTRY(tegra_cpu_wfi) 76 cpu_id r0 77 cpu_to_halt_reg r1, r0 78 cpu_to_csr_reg r2, r0 79 mov32 r0, TEGRA_FLOW_CTRL_VIRT 80 mov r3, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG 81 str r3, [r0, r2] @ clear event & interrupt status 82 mov r3, #FLOW_CTRL_WAIT_FOR_INTERRUPT | FLOW_CTRL_JTAG_RESUME 83 str r3, [r0, r1] @ put flow controller in wait irq mode 84 dsb 85 wfi 86 mov r3, #0 87 str r3, [r0, r1] @ clear flow controller halt status 88 mov r3, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG 89 str r3, [r0, r2] @ clear event & interrupt status 90 dsb 91 mov pc, lr 92ENDPROC(tegra_cpu_wfi) 93 94