1 /* 2 * Copyright (c) 2021, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <stdint.h> 8 #include <stdbool.h> 9 10 #include <common/debug.h> 11 #include <common/runtime_svc.h> 12 #include <drivers/arm/ethosn.h> 13 #include <drivers/delay_timer.h> 14 #include <lib/mmio.h> 15 #include <plat/arm/common/fconf_ethosn_getter.h> 16 17 /* 18 * Number of Arm Ethos-N NPU (NPU) cores available for a 19 * particular parent device 20 */ 21 #define ETHOSN_NUM_CORES \ 22 FCONF_GET_PROPERTY(hw_config, ethosn_config, num_cores) 23 24 /* Address to an NPU core */ 25 #define ETHOSN_CORE_ADDR(core_idx) \ 26 FCONF_GET_PROPERTY(hw_config, ethosn_core_addr, core_idx) 27 28 /* NPU core sec registry address */ 29 #define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \ 30 (core_addr + reg_offset) 31 32 /* Reset timeout in us */ 33 #define ETHOSN_RESET_TIMEOUT_US U(10 * 1000 * 1000) 34 #define ETHOSN_RESET_WAIT_US U(1) 35 36 #define SEC_DEL_REG U(0x0004) 37 #define SEC_DEL_VAL U(0x81C) 38 #define SEC_DEL_EXCC_MASK U(0x20) 39 40 #define SEC_SECCTLR_REG U(0x0010) 41 #define SEC_SECCTLR_VAL U(0x3) 42 43 #define SEC_DEL_MMUSID_REG U(0x2008) 44 #define SEC_DEL_MMUSID_VAL U(0x3FFFF) 45 46 #define SEC_DEL_ADDR_EXT_REG U(0x201C) 47 #define SEC_DEL_ADDR_EXT_VAL U(0x15) 48 49 #define SEC_SYSCTRL0_REG U(0x0018) 50 #define SEC_SYSCTRL0_SOFT_RESET U(3U << 29) 51 #define SEC_SYSCTRL0_HARD_RESET U(1U << 31) 52 53 static bool ethosn_is_core_addr_valid(uintptr_t core_addr) 54 { 55 for (uint32_t core_idx = 0U; core_idx < ETHOSN_NUM_CORES; core_idx++) { 56 if (ETHOSN_CORE_ADDR(core_idx) == core_addr) { 57 return true; 58 } 59 } 60 61 return false; 62 } 63 64 static void ethosn_delegate_to_ns(uintptr_t core_addr) 65 { 66 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG), 67 SEC_SECCTLR_VAL); 68 69 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG), 70 SEC_DEL_VAL); 71 72 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_MMUSID_REG), 73 SEC_DEL_MMUSID_VAL); 74 75 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG), 76 SEC_DEL_ADDR_EXT_VAL); 77 } 78 79 static int ethosn_is_sec(uintptr_t core_addr) 80 { 81 if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG)) 82 & SEC_DEL_EXCC_MASK) != 0U) { 83 return 0; 84 } 85 86 return 1; 87 } 88 89 static bool ethosn_reset(uintptr_t core_addr, int hard_reset) 90 { 91 unsigned int timeout; 92 const uintptr_t sysctrl0_reg = 93 ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG); 94 const uint32_t reset_val = (hard_reset != 0) ? SEC_SYSCTRL0_HARD_RESET 95 : SEC_SYSCTRL0_SOFT_RESET; 96 97 mmio_write_32(sysctrl0_reg, reset_val); 98 99 /* Wait for reset to complete */ 100 for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US; 101 timeout += ETHOSN_RESET_WAIT_US) { 102 103 if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) { 104 break; 105 } 106 107 udelay(ETHOSN_RESET_WAIT_US); 108 } 109 110 return timeout < ETHOSN_RESET_TIMEOUT_US; 111 } 112 113 uintptr_t ethosn_smc_handler(uint32_t smc_fid, 114 u_register_t core_addr, 115 u_register_t x2, 116 u_register_t x3, 117 u_register_t x4, 118 void *cookie, 119 void *handle, 120 u_register_t flags) 121 { 122 int hard_reset = 0; 123 const uint32_t fid = smc_fid & FUNCID_NUM_MASK; 124 125 /* Only SiP fast calls are expected */ 126 if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) || 127 (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) { 128 SMC_RET1(handle, SMC_UNK); 129 } 130 131 /* Truncate parameters to 32-bits for SMC32 */ 132 if (GET_SMC_CC(smc_fid) == SMC_32) { 133 core_addr &= 0xFFFFFFFF; 134 x2 &= 0xFFFFFFFF; 135 x3 &= 0xFFFFFFFF; 136 x4 &= 0xFFFFFFFF; 137 } 138 139 if (!is_ethosn_fid(smc_fid)) { 140 SMC_RET1(handle, SMC_UNK); 141 } 142 143 /* Commands that do not require a valid core address */ 144 switch (fid) { 145 case ETHOSN_FNUM_VERSION: 146 SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR); 147 } 148 149 if (!ethosn_is_core_addr_valid(core_addr)) { 150 WARN("ETHOSN: Unknown core address given to SMC call.\n"); 151 SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS); 152 } 153 154 /* Commands that require a valid addr */ 155 switch (fid) { 156 case ETHOSN_FNUM_IS_SEC: 157 SMC_RET1(handle, ethosn_is_sec(core_addr)); 158 case ETHOSN_FNUM_HARD_RESET: 159 hard_reset = 1; 160 /* Fallthrough */ 161 case ETHOSN_FNUM_SOFT_RESET: 162 if (!ethosn_reset(core_addr, hard_reset)) { 163 SMC_RET1(handle, ETHOSN_FAILURE); 164 } 165 ethosn_delegate_to_ns(core_addr); 166 SMC_RET1(handle, ETHOSN_SUCCESS); 167 default: 168 SMC_RET1(handle, SMC_UNK); 169 } 170 } 171