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