1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * Copyright (c) 2020-2023, NVIDIA Corporation. All rights reserved. 4*91f16700Schasinglulu * 5*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #include <inttypes.h> 9*91f16700Schasinglulu #include <stdint.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <arch.h> 12*91f16700Schasinglulu #include <arch_helpers.h> 13*91f16700Schasinglulu #include <assert.h> 14*91f16700Schasinglulu #include <common/bl_common.h> 15*91f16700Schasinglulu #include <common/debug.h> 16*91f16700Schasinglulu #include <common/runtime_svc.h> 17*91f16700Schasinglulu #include <errno.h> 18*91f16700Schasinglulu #include <lib/mmio.h> 19*91f16700Schasinglulu #include <lib/utils_def.h> 20*91f16700Schasinglulu 21*91f16700Schasinglulu #include <memctrl.h> 22*91f16700Schasinglulu #include <pmc.h> 23*91f16700Schasinglulu #include <tegra_private.h> 24*91f16700Schasinglulu #include <tegra_platform.h> 25*91f16700Schasinglulu #include <tegra_def.h> 26*91f16700Schasinglulu 27*91f16700Schasinglulu /******************************************************************************* 28*91f16700Schasinglulu * PMC parameters 29*91f16700Schasinglulu ******************************************************************************/ 30*91f16700Schasinglulu #define PMC_READ U(0xaa) 31*91f16700Schasinglulu #define PMC_WRITE U(0xbb) 32*91f16700Schasinglulu 33*91f16700Schasinglulu /******************************************************************************* 34*91f16700Schasinglulu * Tegra210 SiP SMCs 35*91f16700Schasinglulu ******************************************************************************/ 36*91f16700Schasinglulu #define TEGRA_SIP_PMC_COMMANDS U(0xC200FE00) 37*91f16700Schasinglulu 38*91f16700Schasinglulu /******************************************************************************* 39*91f16700Schasinglulu * This function is responsible for handling all T210 SiP calls 40*91f16700Schasinglulu ******************************************************************************/ 41*91f16700Schasinglulu int plat_sip_handler(uint32_t smc_fid, 42*91f16700Schasinglulu uint64_t x1, 43*91f16700Schasinglulu uint64_t x2, 44*91f16700Schasinglulu uint64_t x3, 45*91f16700Schasinglulu uint64_t x4, 46*91f16700Schasinglulu const void *cookie, 47*91f16700Schasinglulu void *handle, 48*91f16700Schasinglulu uint64_t flags) 49*91f16700Schasinglulu { 50*91f16700Schasinglulu uint32_t val, ns; 51*91f16700Schasinglulu 52*91f16700Schasinglulu /* Determine which security state this SMC originated from */ 53*91f16700Schasinglulu ns = is_caller_non_secure(flags); 54*91f16700Schasinglulu if (!ns) 55*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 56*91f16700Schasinglulu 57*91f16700Schasinglulu if (smc_fid == TEGRA_SIP_PMC_COMMANDS) { 58*91f16700Schasinglulu 59*91f16700Schasinglulu /* check the address is within PMC range and is 4byte aligned */ 60*91f16700Schasinglulu if ((x2 >= TEGRA_PMC_SIZE) || (x2 & 0x3)) { 61*91f16700Schasinglulu return -EINVAL; 62*91f16700Schasinglulu } 63*91f16700Schasinglulu 64*91f16700Schasinglulu switch (x2) { 65*91f16700Schasinglulu /* Black listed PMC registers */ 66*91f16700Schasinglulu case PMC_SCRATCH1: 67*91f16700Schasinglulu case PMC_SCRATCH31 ... PMC_SCRATCH33: 68*91f16700Schasinglulu case PMC_SCRATCH40: 69*91f16700Schasinglulu case PMC_SCRATCH42: 70*91f16700Schasinglulu case PMC_SCRATCH43 ... PMC_SCRATCH48: 71*91f16700Schasinglulu case PMC_SCRATCH50 ... PMC_SCRATCH51: 72*91f16700Schasinglulu case PMC_SCRATCH56 ... PMC_SCRATCH57: 73*91f16700Schasinglulu /* PMC secure-only registers are not accessible */ 74*91f16700Schasinglulu case PMC_DPD_ENABLE_0: 75*91f16700Schasinglulu case PMC_FUSE_CONTROL_0: 76*91f16700Schasinglulu case PMC_CRYPTO_OP_0: 77*91f16700Schasinglulu case PMC_TSC_MULT_0: 78*91f16700Schasinglulu case PMC_STICKY_BIT: 79*91f16700Schasinglulu ERROR("%s: error offset=0x%" PRIx64 "\n", __func__, x2); 80*91f16700Schasinglulu return -EFAULT; 81*91f16700Schasinglulu default: 82*91f16700Schasinglulu /* Valid register */ 83*91f16700Schasinglulu break; 84*91f16700Schasinglulu } 85*91f16700Schasinglulu 86*91f16700Schasinglulu /* Perform PMC read/write */ 87*91f16700Schasinglulu if (x1 == PMC_READ) { 88*91f16700Schasinglulu val = mmio_read_32((uint32_t)(TEGRA_PMC_BASE + x2)); 89*91f16700Schasinglulu write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X1, val); 90*91f16700Schasinglulu } else if (x1 == PMC_WRITE) { 91*91f16700Schasinglulu mmio_write_32((uint32_t)(TEGRA_PMC_BASE + x2), (uint32_t)x3); 92*91f16700Schasinglulu } else { 93*91f16700Schasinglulu return -EINVAL; 94*91f16700Schasinglulu } 95*91f16700Schasinglulu } else { 96*91f16700Schasinglulu return -ENOTSUP; 97*91f16700Schasinglulu } 98*91f16700Schasinglulu return 0; 99*91f16700Schasinglulu } 100