1 /* 2 * Copyright (c) 2021-2022, 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_SOFT_RESET U(3U << 29) 47 #define SEC_SYSCTRL0_HARD_RESET U(1U << 31) 48 49 #define SEC_MMUSID_REG_BASE U(0x3008) 50 #define SEC_MMUSID_OFFSET U(0x1000) 51 52 static bool ethosn_get_device_and_core(uintptr_t core_addr, 53 const struct ethosn_device_t **dev_match, 54 const struct ethosn_core_t **core_match) 55 { 56 uint32_t dev_idx; 57 uint32_t core_idx; 58 59 for (dev_idx = 0U; dev_idx < ETHOSN_NUM_DEVICES; ++dev_idx) { 60 const struct ethosn_device_t *dev = ETHOSN_GET_DEVICE(dev_idx); 61 62 for (core_idx = 0U; core_idx < dev->num_cores; ++core_idx) { 63 const struct ethosn_core_t *core = &(dev->cores[core_idx]); 64 65 if (core->addr == core_addr) { 66 *dev_match = dev; 67 *core_match = core; 68 return true; 69 } 70 } 71 } 72 73 WARN("ETHOSN: Unknown core address given to SMC call.\n"); 74 return false; 75 } 76 77 static void ethosn_configure_smmu_streams(const struct ethosn_device_t *device, 78 const struct ethosn_core_t *core, 79 uint32_t asset_alloc_idx) 80 { 81 const struct ethosn_main_allocator_t *main_alloc = 82 &(core->main_allocator); 83 const struct ethosn_asset_allocator_t *asset_alloc = 84 &(device->asset_allocators[asset_alloc_idx]); 85 const uint32_t streams[9] = { 86 main_alloc->firmware.stream_id, 87 main_alloc->working_data.stream_id, 88 asset_alloc->command_stream.stream_id, 89 0U, /* Not used*/ 90 main_alloc->firmware.stream_id, 91 asset_alloc->weight_data.stream_id, 92 asset_alloc->buffer_data.stream_id, 93 asset_alloc->intermediate_data.stream_id, 94 asset_alloc->buffer_data.stream_id 95 }; 96 size_t i; 97 98 for (i = 0U; i < ARRAY_SIZE(streams); ++i) { 99 const uintptr_t reg_addr = SEC_MMUSID_REG_BASE + 100 (SEC_MMUSID_OFFSET * i); 101 mmio_write_32(ETHOSN_CORE_SEC_REG(core->addr, reg_addr), 102 streams[i]); 103 } 104 } 105 106 static void ethosn_delegate_to_ns(uintptr_t core_addr) 107 { 108 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG), 109 SEC_SECCTLR_VAL); 110 111 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG), 112 SEC_DEL_VAL); 113 114 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG), 115 SEC_DEL_ADDR_EXT_VAL); 116 } 117 118 static int ethosn_is_sec(uintptr_t core_addr) 119 { 120 if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG)) 121 & SEC_DEL_EXCC_MASK) != 0U) { 122 return 0; 123 } 124 125 return 1; 126 } 127 128 static bool ethosn_reset(uintptr_t core_addr, int hard_reset) 129 { 130 unsigned int timeout; 131 const uintptr_t sysctrl0_reg = 132 ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG); 133 const uint32_t reset_val = (hard_reset != 0) ? SEC_SYSCTRL0_HARD_RESET 134 : SEC_SYSCTRL0_SOFT_RESET; 135 136 mmio_write_32(sysctrl0_reg, reset_val); 137 138 /* Wait for reset to complete */ 139 for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US; 140 timeout += ETHOSN_RESET_WAIT_US) { 141 142 if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) { 143 break; 144 } 145 146 udelay(ETHOSN_RESET_WAIT_US); 147 } 148 149 return timeout < ETHOSN_RESET_TIMEOUT_US; 150 } 151 152 uintptr_t ethosn_smc_handler(uint32_t smc_fid, 153 u_register_t core_addr, 154 u_register_t asset_alloc_idx, 155 u_register_t x3, 156 u_register_t x4, 157 void *cookie, 158 void *handle, 159 u_register_t flags) 160 { 161 int hard_reset = 0; 162 const struct ethosn_device_t *device = NULL; 163 const struct ethosn_core_t *core = NULL; 164 const uint32_t fid = smc_fid & FUNCID_NUM_MASK; 165 166 /* Only SiP fast calls are expected */ 167 if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) || 168 (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) { 169 SMC_RET1(handle, SMC_UNK); 170 } 171 172 /* Truncate parameters to 32-bits for SMC32 */ 173 if (GET_SMC_CC(smc_fid) == SMC_32) { 174 core_addr &= 0xFFFFFFFF; 175 asset_alloc_idx &= 0xFFFFFFFF; 176 x3 &= 0xFFFFFFFF; 177 x4 &= 0xFFFFFFFF; 178 } 179 180 if (!is_ethosn_fid(smc_fid) || 181 (fid < ETHOSN_FNUM_VERSION || fid > ETHOSN_FNUM_SOFT_RESET)) { 182 WARN("ETHOSN: Unknown SMC call: 0x%x\n", smc_fid); 183 SMC_RET1(handle, SMC_UNK); 184 } 185 186 /* Commands that do not require a valid core address */ 187 switch (fid) { 188 case ETHOSN_FNUM_VERSION: 189 SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR); 190 } 191 192 if (!ethosn_get_device_and_core(core_addr, &device, &core)) { 193 SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS); 194 } 195 196 /* Commands that require a valid core address */ 197 switch (fid) { 198 case ETHOSN_FNUM_IS_SEC: 199 SMC_RET1(handle, ethosn_is_sec(core->addr)); 200 } 201 202 if (!device->has_reserved_memory && 203 asset_alloc_idx >= device->num_allocators) { 204 WARN("ETHOSN: Unknown asset allocator index given to SMC call.\n"); 205 SMC_RET1(handle, ETHOSN_UNKNOWN_ALLOCATOR_IDX); 206 } 207 208 /* Commands that require a valid device, core and asset allocator */ 209 switch (fid) { 210 case ETHOSN_FNUM_HARD_RESET: 211 hard_reset = 1; 212 /* Fallthrough */ 213 case ETHOSN_FNUM_SOFT_RESET: 214 if (!ethosn_reset(core->addr, hard_reset)) { 215 SMC_RET1(handle, ETHOSN_FAILURE); 216 } 217 218 if (!device->has_reserved_memory) { 219 ethosn_configure_smmu_streams(device, core, 220 asset_alloc_idx); 221 } 222 223 ethosn_delegate_to_ns(core->addr); 224 SMC_RET1(handle, ETHOSN_SUCCESS); 225 default: 226 WARN("ETHOSN: Unimplemented SMC call: 0x%x\n", fid); 227 SMC_RET1(handle, SMC_UNK); 228 } 229 } 230