1 /* 2 * Copyright (c) 2021-2023, 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 <lib/utils_def.h> 16 #include <plat/arm/common/fconf_ethosn_getter.h> 17 18 /* 19 * Number of Arm(R) Ethos(TM)-N NPU (NPU) devices available 20 */ 21 #define ETHOSN_NUM_DEVICES \ 22 FCONF_GET_PROPERTY(hw_config, ethosn_config, num_devices) 23 24 #define ETHOSN_GET_DEVICE(dev_idx) \ 25 FCONF_GET_PROPERTY(hw_config, ethosn_device, dev_idx) 26 27 /* NPU core sec registry address */ 28 #define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \ 29 (core_addr + reg_offset) 30 31 /* Reset timeout in us */ 32 #define ETHOSN_RESET_TIMEOUT_US U(10 * 1000 * 1000) 33 #define ETHOSN_RESET_WAIT_US U(1) 34 35 #define SEC_DEL_REG U(0x0004) 36 #define SEC_DEL_VAL U(0x81C) 37 #define SEC_DEL_EXCC_MASK U(0x20) 38 39 #define SEC_SECCTLR_REG U(0x0010) 40 #define SEC_SECCTLR_VAL U(0x3) 41 42 #define SEC_DEL_ADDR_EXT_REG U(0x201C) 43 #define SEC_DEL_ADDR_EXT_VAL U(0x15) 44 45 #define SEC_SYSCTRL0_REG U(0x0018) 46 #define SEC_SYSCTRL0_SLEEPING U(1U << 4) 47 #define SEC_SYSCTRL0_SOFT_RESET U(3U << 29) 48 #define SEC_SYSCTRL0_HARD_RESET U(1U << 31) 49 50 #define SEC_MMUSID_REG_BASE U(0x3008) 51 #define SEC_MMUSID_OFFSET U(0x1000) 52 53 static bool ethosn_get_device_and_core(uintptr_t core_addr, 54 const struct ethosn_device_t **dev_match, 55 const struct ethosn_core_t **core_match) 56 { 57 uint32_t dev_idx; 58 uint32_t core_idx; 59 60 for (dev_idx = 0U; dev_idx < ETHOSN_NUM_DEVICES; ++dev_idx) { 61 const struct ethosn_device_t *dev = ETHOSN_GET_DEVICE(dev_idx); 62 63 for (core_idx = 0U; core_idx < dev->num_cores; ++core_idx) { 64 const struct ethosn_core_t *core = &(dev->cores[core_idx]); 65 66 if (core->addr == core_addr) { 67 *dev_match = dev; 68 *core_match = core; 69 return true; 70 } 71 } 72 } 73 74 WARN("ETHOSN: Unknown core address given to SMC call.\n"); 75 return false; 76 } 77 78 static void ethosn_configure_smmu_streams(const struct ethosn_device_t *device, 79 const struct ethosn_core_t *core, 80 uint32_t asset_alloc_idx) 81 { 82 const struct ethosn_main_allocator_t *main_alloc = 83 &(core->main_allocator); 84 const struct ethosn_asset_allocator_t *asset_alloc = 85 &(device->asset_allocators[asset_alloc_idx]); 86 const uint32_t streams[9] = { 87 main_alloc->firmware.stream_id, 88 main_alloc->working_data.stream_id, 89 asset_alloc->command_stream.stream_id, 90 0U, /* Not used*/ 91 main_alloc->firmware.stream_id, 92 asset_alloc->weight_data.stream_id, 93 asset_alloc->buffer_data.stream_id, 94 asset_alloc->intermediate_data.stream_id, 95 asset_alloc->buffer_data.stream_id 96 }; 97 size_t i; 98 99 for (i = 0U; i < ARRAY_SIZE(streams); ++i) { 100 const uintptr_t reg_addr = SEC_MMUSID_REG_BASE + 101 (SEC_MMUSID_OFFSET * i); 102 mmio_write_32(ETHOSN_CORE_SEC_REG(core->addr, reg_addr), 103 streams[i]); 104 } 105 } 106 107 static void ethosn_delegate_to_ns(uintptr_t core_addr) 108 { 109 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG), 110 SEC_SECCTLR_VAL); 111 112 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG), 113 SEC_DEL_VAL); 114 115 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG), 116 SEC_DEL_ADDR_EXT_VAL); 117 } 118 119 static int ethosn_is_sec(uintptr_t core_addr) 120 { 121 if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG)) 122 & SEC_DEL_EXCC_MASK) != 0U) { 123 return 0; 124 } 125 126 return 1; 127 } 128 129 static int ethosn_core_is_sleeping(uintptr_t core_addr) 130 { 131 const uintptr_t sysctrl0_reg = 132 ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG); 133 const uint32_t sleeping_mask = SEC_SYSCTRL0_SLEEPING; 134 135 return ((mmio_read_32(sysctrl0_reg) & sleeping_mask) == sleeping_mask); 136 } 137 138 static bool ethosn_reset(uintptr_t core_addr, int hard_reset) 139 { 140 unsigned int timeout; 141 const uintptr_t sysctrl0_reg = 142 ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG); 143 const uint32_t reset_val = (hard_reset != 0) ? SEC_SYSCTRL0_HARD_RESET 144 : SEC_SYSCTRL0_SOFT_RESET; 145 146 mmio_write_32(sysctrl0_reg, reset_val); 147 148 /* Wait for reset to complete */ 149 for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US; 150 timeout += ETHOSN_RESET_WAIT_US) { 151 152 if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) { 153 break; 154 } 155 156 udelay(ETHOSN_RESET_WAIT_US); 157 } 158 159 return timeout < ETHOSN_RESET_TIMEOUT_US; 160 } 161 162 uintptr_t ethosn_smc_handler(uint32_t smc_fid, 163 u_register_t core_addr, 164 u_register_t asset_alloc_idx, 165 u_register_t reset_type, 166 u_register_t x4, 167 void *cookie, 168 void *handle, 169 u_register_t flags) 170 { 171 int hard_reset = 0; 172 const struct ethosn_device_t *device = NULL; 173 const struct ethosn_core_t *core = NULL; 174 const uint32_t fid = smc_fid & FUNCID_NUM_MASK; 175 176 /* Only SiP fast calls are expected */ 177 if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) || 178 (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) { 179 SMC_RET1(handle, SMC_UNK); 180 } 181 182 /* Truncate parameters to 32-bits for SMC32 */ 183 if (GET_SMC_CC(smc_fid) == SMC_32) { 184 core_addr &= 0xFFFFFFFF; 185 asset_alloc_idx &= 0xFFFFFFFF; 186 reset_type &= 0xFFFFFFFF; 187 x4 &= 0xFFFFFFFF; 188 } 189 190 if (!is_ethosn_fid(smc_fid) || (fid > ETHOSN_FNUM_IS_SLEEPING)) { 191 WARN("ETHOSN: Unknown SMC call: 0x%x\n", smc_fid); 192 SMC_RET1(handle, SMC_UNK); 193 } 194 195 /* Commands that do not require a valid core address */ 196 switch (fid) { 197 case ETHOSN_FNUM_VERSION: 198 SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR); 199 } 200 201 if (!ethosn_get_device_and_core(core_addr, &device, &core)) { 202 SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS); 203 } 204 205 /* Commands that require a valid core address */ 206 switch (fid) { 207 case ETHOSN_FNUM_IS_SEC: 208 SMC_RET1(handle, ethosn_is_sec(core->addr)); 209 case ETHOSN_FNUM_IS_SLEEPING: 210 SMC_RET1(handle, ethosn_core_is_sleeping(core->addr)); 211 } 212 213 if (!device->has_reserved_memory && 214 asset_alloc_idx >= device->num_allocators) { 215 WARN("ETHOSN: Unknown asset allocator index given to SMC call.\n"); 216 SMC_RET1(handle, ETHOSN_UNKNOWN_ALLOCATOR_IDX); 217 } 218 219 if (reset_type > ETHOSN_RESET_TYPE_HALT) { 220 WARN("ETHOSN: Invalid reset type given to SMC call.\n"); 221 SMC_RET1(handle, ETHOSN_INVALID_PARAMETER); 222 } 223 224 /* 225 * Commands that require a valid device, reset type, 226 * core and asset allocator 227 */ 228 switch (fid) { 229 case ETHOSN_FNUM_HARD_RESET: 230 hard_reset = 1; 231 /* Fallthrough */ 232 case ETHOSN_FNUM_SOFT_RESET: 233 if (!ethosn_reset(core->addr, hard_reset)) { 234 SMC_RET1(handle, ETHOSN_FAILURE); 235 } 236 237 if (reset_type == ETHOSN_RESET_TYPE_FULL) { 238 if (!device->has_reserved_memory) { 239 ethosn_configure_smmu_streams(device, core, 240 asset_alloc_idx); 241 } 242 243 ethosn_delegate_to_ns(core->addr); 244 } 245 SMC_RET1(handle, ETHOSN_SUCCESS); 246 default: 247 WARN("ETHOSN: Unimplemented SMC call: 0x%x\n", fid); 248 SMC_RET1(handle, SMC_UNK); 249 } 250 } 251