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 /* Arm Ethos-N NPU (NPU) status */ 18 #define ETHOSN_STATUS \ 19 FCONF_GET_PROPERTY(hw_config, ethosn_config, status) 20 21 /* Number of NPU cores available */ 22 #define ETHOSN_NUM_CORES \ 23 FCONF_GET_PROPERTY(hw_config, ethosn_config, num_cores) 24 25 /* Address to an NPU core */ 26 #define ETHOSN_CORE_ADDR(core_idx) \ 27 FCONF_GET_PROPERTY(hw_config, ethosn_core_addr, core_idx) 28 29 /* NPU core sec registry address */ 30 #define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \ 31 (core_addr + reg_offset) 32 33 /* Reset timeout in us */ 34 #define ETHOSN_RESET_TIMEOUT_US U(10 * 1000 * 1000) 35 #define ETHOSN_RESET_WAIT_US U(1) 36 37 #define SEC_DEL_REG U(0x0004) 38 #define SEC_DEL_VAL U(0x81C) 39 #define SEC_DEL_EXCC_MASK U(0x20) 40 41 #define SEC_SECCTLR_REG U(0x0010) 42 #define SEC_SECCTLR_VAL U(0x3) 43 44 #define SEC_DEL_MMUSID_REG U(0x2008) 45 #define SEC_DEL_MMUSID_VAL U(0x3FFFF) 46 47 #define SEC_DEL_ADDR_EXT_REG U(0x201C) 48 #define SEC_DEL_ADDR_EXT_VAL U(0x15) 49 50 #define SEC_SYSCTRL0_REG U(0x0018) 51 #define SEC_SYSCTRL0_SOFT_RESET U(3U << 29) 52 #define SEC_SYSCTRL0_HARD_RESET U(1U << 31) 53 54 static void ethosn_delegate_to_ns(uintptr_t core_addr) 55 { 56 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG), 57 SEC_SECCTLR_VAL); 58 59 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG), 60 SEC_DEL_VAL); 61 62 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_MMUSID_REG), 63 SEC_DEL_MMUSID_VAL); 64 65 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG), 66 SEC_DEL_ADDR_EXT_VAL); 67 } 68 69 static int ethosn_is_sec(void) 70 { 71 if ((mmio_read_32(ETHOSN_CORE_SEC_REG(ETHOSN_CORE_ADDR(0), SEC_DEL_REG)) 72 & SEC_DEL_EXCC_MASK) != 0U) { 73 return 0; 74 } 75 76 return 1; 77 } 78 79 static bool ethosn_reset(uintptr_t core_addr, int hard_reset) 80 { 81 unsigned int timeout; 82 const uintptr_t sysctrl0_reg = 83 ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG); 84 const uint32_t reset_val = (hard_reset != 0) ? SEC_SYSCTRL0_HARD_RESET 85 : SEC_SYSCTRL0_SOFT_RESET; 86 87 mmio_write_32(sysctrl0_reg, reset_val); 88 89 /* Wait for reset to complete */ 90 for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US; 91 timeout += ETHOSN_RESET_WAIT_US) { 92 93 if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) { 94 break; 95 } 96 97 udelay(ETHOSN_RESET_WAIT_US); 98 } 99 100 return timeout < ETHOSN_RESET_TIMEOUT_US; 101 } 102 103 uintptr_t ethosn_smc_handler(uint32_t smc_fid, 104 u_register_t core_idx, 105 u_register_t x2, 106 u_register_t x3, 107 u_register_t x4, 108 void *cookie, 109 void *handle, 110 u_register_t flags) 111 { 112 uintptr_t core_addr; 113 int hard_reset = 0; 114 115 /* Only SiP fast calls are expected */ 116 if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) || 117 (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) { 118 SMC_RET1(handle, SMC_UNK); 119 } 120 121 /* Truncate parameters to 32-bits for SMC32 */ 122 if (GET_SMC_CC(smc_fid) == SMC_32) { 123 core_idx &= 0xFFFFFFFF; 124 x2 &= 0xFFFFFFFF; 125 x3 &= 0xFFFFFFFF; 126 x4 &= 0xFFFFFFFF; 127 } 128 129 if (!is_ethosn_fid(smc_fid)) { 130 SMC_RET1(handle, SMC_UNK); 131 } 132 133 if (ETHOSN_STATUS == ETHOSN_STATUS_DISABLED) { 134 WARN("ETHOSN: Arm Ethos-N NPU not available\n"); 135 SMC_RET1(handle, ETHOSN_NOT_SUPPORTED); 136 } 137 138 switch (smc_fid & FUNCID_NUM_MASK) { 139 case ETHOSN_FNUM_VERSION: 140 SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR); 141 case ETHOSN_FNUM_IS_SEC: 142 SMC_RET1(handle, ethosn_is_sec()); 143 case ETHOSN_FNUM_HARD_RESET: 144 hard_reset = 1; 145 /* Fallthrough */ 146 case ETHOSN_FNUM_SOFT_RESET: 147 if (core_idx >= ETHOSN_NUM_CORES) { 148 WARN("ETHOSN: core index out of range\n"); 149 SMC_RET1(handle, ETHOSN_CORE_IDX_OUT_OF_RANGE); 150 } 151 152 core_addr = ETHOSN_CORE_ADDR(core_idx); 153 154 if (!ethosn_reset(core_addr, hard_reset)) { 155 SMC_RET1(handle, ETHOSN_FAILURE); 156 } 157 158 ethosn_delegate_to_ns(core_addr); 159 160 SMC_RET1(handle, ETHOSN_SUCCESS); 161 default: 162 SMC_RET1(handle, SMC_UNK); 163 } 164 } 165