1 /* 2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch.h> 8 #include <arch_helpers.h> 9 #include <assert.h> 10 #include <bl_common.h> 11 #include <context_mgmt.h> 12 #include <debug.h> 13 #include <errno.h> 14 #include <tegra_private.h> 15 16 #define NS_SWITCH_AARCH32 1 17 #define SCR_RW_BITPOS __builtin_ctz(SCR_RW_BIT) 18 19 /******************************************************************************* 20 * Tegra132 SiP SMCs 21 ******************************************************************************/ 22 #define TEGRA_SIP_AARCH_SWITCH 0x82000004 23 24 /******************************************************************************* 25 * SPSR settings for AARCH32/AARCH64 modes 26 ******************************************************************************/ 27 #define SPSR32 SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE, \ 28 DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT) 29 #define SPSR64 SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS) 30 31 /******************************************************************************* 32 * This function is responsible for handling all T132 SiP calls 33 ******************************************************************************/ 34 int plat_sip_handler(uint32_t smc_fid, 35 uint64_t x1, 36 uint64_t x2, 37 uint64_t x3, 38 uint64_t x4, 39 void *cookie, 40 void *handle, 41 uint64_t flags) 42 { 43 switch (smc_fid) { 44 45 case TEGRA_SIP_AARCH_SWITCH: 46 47 /* clean up the high bits */ 48 x1 = (uint32_t)x1; 49 x2 = (uint32_t)x2; 50 51 if (!x1 || x2 > NS_SWITCH_AARCH32) { 52 ERROR("%s: invalid parameters\n", __func__); 53 return -EINVAL; 54 } 55 56 /* x1 = ns entry point */ 57 cm_set_elr_spsr_el3(NON_SECURE, x1, 58 (x2 == NS_SWITCH_AARCH32) ? SPSR32 : SPSR64); 59 60 /* switch NS world mode */ 61 cm_write_scr_el3_bit(NON_SECURE, SCR_RW_BITPOS, !x2); 62 63 INFO("CPU switched to AARCH%s mode\n", 64 (x2 == NS_SWITCH_AARCH32) ? "32" : "64"); 65 return 0; 66 67 default: 68 ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); 69 break; 70 } 71 72 return -ENOTSUP; 73 } 74