176a21174SMikael Olsson /* 276a21174SMikael Olsson * Copyright (c) 2021, Arm Limited. All rights reserved. 376a21174SMikael Olsson * 476a21174SMikael Olsson * SPDX-License-Identifier: BSD-3-Clause 576a21174SMikael Olsson */ 676a21174SMikael Olsson 776a21174SMikael Olsson #include <stdint.h> 876a21174SMikael Olsson #include <stdbool.h> 976a21174SMikael Olsson 1076a21174SMikael Olsson #include <common/debug.h> 1176a21174SMikael Olsson #include <common/runtime_svc.h> 1276a21174SMikael Olsson #include <drivers/arm/ethosn.h> 1376a21174SMikael Olsson #include <drivers/delay_timer.h> 1476a21174SMikael Olsson #include <lib/mmio.h> 1576a21174SMikael Olsson #include <plat/arm/common/fconf_ethosn_getter.h> 1676a21174SMikael Olsson 17*1c65989eSLaurent Carlier /* 18*1c65989eSLaurent Carlier * Number of Arm Ethos-N NPU (NPU) cores available for a 19*1c65989eSLaurent Carlier * particular parent device 20*1c65989eSLaurent Carlier */ 2176a21174SMikael Olsson #define ETHOSN_NUM_CORES \ 2276a21174SMikael Olsson FCONF_GET_PROPERTY(hw_config, ethosn_config, num_cores) 2376a21174SMikael Olsson 2476a21174SMikael Olsson /* Address to an NPU core */ 2576a21174SMikael Olsson #define ETHOSN_CORE_ADDR(core_idx) \ 2676a21174SMikael Olsson FCONF_GET_PROPERTY(hw_config, ethosn_core_addr, core_idx) 2776a21174SMikael Olsson 2876a21174SMikael Olsson /* NPU core sec registry address */ 2976a21174SMikael Olsson #define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \ 3076a21174SMikael Olsson (core_addr + reg_offset) 3176a21174SMikael Olsson 3276a21174SMikael Olsson /* Reset timeout in us */ 3376a21174SMikael Olsson #define ETHOSN_RESET_TIMEOUT_US U(10 * 1000 * 1000) 3476a21174SMikael Olsson #define ETHOSN_RESET_WAIT_US U(1) 3576a21174SMikael Olsson 3676a21174SMikael Olsson #define SEC_DEL_REG U(0x0004) 3776a21174SMikael Olsson #define SEC_DEL_VAL U(0x81C) 3876a21174SMikael Olsson #define SEC_DEL_EXCC_MASK U(0x20) 3976a21174SMikael Olsson 4076a21174SMikael Olsson #define SEC_SECCTLR_REG U(0x0010) 4176a21174SMikael Olsson #define SEC_SECCTLR_VAL U(0x3) 4276a21174SMikael Olsson 4376a21174SMikael Olsson #define SEC_DEL_MMUSID_REG U(0x2008) 4476a21174SMikael Olsson #define SEC_DEL_MMUSID_VAL U(0x3FFFF) 4576a21174SMikael Olsson 4676a21174SMikael Olsson #define SEC_DEL_ADDR_EXT_REG U(0x201C) 4776a21174SMikael Olsson #define SEC_DEL_ADDR_EXT_VAL U(0x15) 4876a21174SMikael Olsson 4976a21174SMikael Olsson #define SEC_SYSCTRL0_REG U(0x0018) 5076a21174SMikael Olsson #define SEC_SYSCTRL0_SOFT_RESET U(3U << 29) 5176a21174SMikael Olsson #define SEC_SYSCTRL0_HARD_RESET U(1U << 31) 5276a21174SMikael Olsson 53*1c65989eSLaurent Carlier static bool ethosn_is_core_addr_valid(uintptr_t core_addr) 54*1c65989eSLaurent Carlier { 55*1c65989eSLaurent Carlier for (uint32_t core_idx = 0U; core_idx < ETHOSN_NUM_CORES; core_idx++) { 56*1c65989eSLaurent Carlier if (ETHOSN_CORE_ADDR(core_idx) == core_addr) { 57*1c65989eSLaurent Carlier return true; 58*1c65989eSLaurent Carlier } 59*1c65989eSLaurent Carlier } 60*1c65989eSLaurent Carlier 61*1c65989eSLaurent Carlier return false; 62*1c65989eSLaurent Carlier } 63*1c65989eSLaurent Carlier 6476a21174SMikael Olsson static void ethosn_delegate_to_ns(uintptr_t core_addr) 6576a21174SMikael Olsson { 6676a21174SMikael Olsson mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG), 6776a21174SMikael Olsson SEC_SECCTLR_VAL); 6876a21174SMikael Olsson 6976a21174SMikael Olsson mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG), 7076a21174SMikael Olsson SEC_DEL_VAL); 7176a21174SMikael Olsson 7276a21174SMikael Olsson mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_MMUSID_REG), 7376a21174SMikael Olsson SEC_DEL_MMUSID_VAL); 7476a21174SMikael Olsson 7576a21174SMikael Olsson mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG), 7676a21174SMikael Olsson SEC_DEL_ADDR_EXT_VAL); 7776a21174SMikael Olsson } 7876a21174SMikael Olsson 79*1c65989eSLaurent Carlier static int ethosn_is_sec(uintptr_t core_addr) 8076a21174SMikael Olsson { 81*1c65989eSLaurent Carlier if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG)) 8276a21174SMikael Olsson & SEC_DEL_EXCC_MASK) != 0U) { 8376a21174SMikael Olsson return 0; 8476a21174SMikael Olsson } 8576a21174SMikael Olsson 8676a21174SMikael Olsson return 1; 8776a21174SMikael Olsson } 8876a21174SMikael Olsson 8976a21174SMikael Olsson static bool ethosn_reset(uintptr_t core_addr, int hard_reset) 9076a21174SMikael Olsson { 9176a21174SMikael Olsson unsigned int timeout; 9276a21174SMikael Olsson const uintptr_t sysctrl0_reg = 9376a21174SMikael Olsson ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG); 9476a21174SMikael Olsson const uint32_t reset_val = (hard_reset != 0) ? SEC_SYSCTRL0_HARD_RESET 9576a21174SMikael Olsson : SEC_SYSCTRL0_SOFT_RESET; 9676a21174SMikael Olsson 9776a21174SMikael Olsson mmio_write_32(sysctrl0_reg, reset_val); 9876a21174SMikael Olsson 9976a21174SMikael Olsson /* Wait for reset to complete */ 10076a21174SMikael Olsson for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US; 10176a21174SMikael Olsson timeout += ETHOSN_RESET_WAIT_US) { 10276a21174SMikael Olsson 10376a21174SMikael Olsson if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) { 10476a21174SMikael Olsson break; 10576a21174SMikael Olsson } 10676a21174SMikael Olsson 10776a21174SMikael Olsson udelay(ETHOSN_RESET_WAIT_US); 10876a21174SMikael Olsson } 10976a21174SMikael Olsson 11076a21174SMikael Olsson return timeout < ETHOSN_RESET_TIMEOUT_US; 11176a21174SMikael Olsson } 11276a21174SMikael Olsson 11376a21174SMikael Olsson uintptr_t ethosn_smc_handler(uint32_t smc_fid, 114*1c65989eSLaurent Carlier u_register_t core_addr, 11576a21174SMikael Olsson u_register_t x2, 11676a21174SMikael Olsson u_register_t x3, 11776a21174SMikael Olsson u_register_t x4, 11876a21174SMikael Olsson void *cookie, 11976a21174SMikael Olsson void *handle, 12076a21174SMikael Olsson u_register_t flags) 12176a21174SMikael Olsson { 12276a21174SMikael Olsson int hard_reset = 0; 123*1c65989eSLaurent Carlier const uint32_t fid = smc_fid & FUNCID_NUM_MASK; 12476a21174SMikael Olsson 12576a21174SMikael Olsson /* Only SiP fast calls are expected */ 12676a21174SMikael Olsson if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) || 12776a21174SMikael Olsson (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) { 12876a21174SMikael Olsson SMC_RET1(handle, SMC_UNK); 12976a21174SMikael Olsson } 13076a21174SMikael Olsson 13176a21174SMikael Olsson /* Truncate parameters to 32-bits for SMC32 */ 13276a21174SMikael Olsson if (GET_SMC_CC(smc_fid) == SMC_32) { 133*1c65989eSLaurent Carlier core_addr &= 0xFFFFFFFF; 13476a21174SMikael Olsson x2 &= 0xFFFFFFFF; 13576a21174SMikael Olsson x3 &= 0xFFFFFFFF; 13676a21174SMikael Olsson x4 &= 0xFFFFFFFF; 13776a21174SMikael Olsson } 13876a21174SMikael Olsson 13976a21174SMikael Olsson if (!is_ethosn_fid(smc_fid)) { 14076a21174SMikael Olsson SMC_RET1(handle, SMC_UNK); 14176a21174SMikael Olsson } 14276a21174SMikael Olsson 143*1c65989eSLaurent Carlier /* Commands that do not require a valid core address */ 144*1c65989eSLaurent Carlier switch (fid) { 14576a21174SMikael Olsson case ETHOSN_FNUM_VERSION: 14676a21174SMikael Olsson SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR); 147*1c65989eSLaurent Carlier } 148*1c65989eSLaurent Carlier 149*1c65989eSLaurent Carlier if (!ethosn_is_core_addr_valid(core_addr)) { 150*1c65989eSLaurent Carlier WARN("ETHOSN: Unknown core address given to SMC call.\n"); 151*1c65989eSLaurent Carlier SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS); 152*1c65989eSLaurent Carlier } 153*1c65989eSLaurent Carlier 154*1c65989eSLaurent Carlier /* Commands that require a valid addr */ 155*1c65989eSLaurent Carlier switch (fid) { 15676a21174SMikael Olsson case ETHOSN_FNUM_IS_SEC: 157*1c65989eSLaurent Carlier SMC_RET1(handle, ethosn_is_sec(core_addr)); 15876a21174SMikael Olsson case ETHOSN_FNUM_HARD_RESET: 15976a21174SMikael Olsson hard_reset = 1; 16076a21174SMikael Olsson /* Fallthrough */ 16176a21174SMikael Olsson case ETHOSN_FNUM_SOFT_RESET: 16276a21174SMikael Olsson if (!ethosn_reset(core_addr, hard_reset)) { 16376a21174SMikael Olsson SMC_RET1(handle, ETHOSN_FAILURE); 16476a21174SMikael Olsson } 16576a21174SMikael Olsson ethosn_delegate_to_ns(core_addr); 16676a21174SMikael Olsson SMC_RET1(handle, ETHOSN_SUCCESS); 16776a21174SMikael Olsson default: 16876a21174SMikael Olsson SMC_RET1(handle, SMC_UNK); 16976a21174SMikael Olsson } 17076a21174SMikael Olsson } 171