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