176a21174SMikael Olsson /* 2fa37d308SJoshua Pimm * Copyright (c) 2021-2023, 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> 15b139f1cfSMikael Olsson #include <lib/utils_def.h> 1676a21174SMikael Olsson #include <plat/arm/common/fconf_ethosn_getter.h> 1776a21174SMikael Olsson 1870a296eeSRajasekaran Kalidoss #include <platform_def.h> 1970a296eeSRajasekaran Kalidoss 20352366edSRajasekaran Kalidoss #if ETHOSN_NPU_TZMP1 21313b776fSMikael Olsson #include "ethosn_big_fw.h" 22352366edSRajasekaran Kalidoss #endif /* ETHOSN_NPU_TZMP1 */ 23313b776fSMikael Olsson 241c65989eSLaurent Carlier /* 25b139f1cfSMikael Olsson * Number of Arm(R) Ethos(TM)-N NPU (NPU) devices available 261c65989eSLaurent Carlier */ 27b139f1cfSMikael Olsson #define ETHOSN_NUM_DEVICES \ 28b139f1cfSMikael Olsson FCONF_GET_PROPERTY(hw_config, ethosn_config, num_devices) 2976a21174SMikael Olsson 30b139f1cfSMikael Olsson #define ETHOSN_GET_DEVICE(dev_idx) \ 31b139f1cfSMikael Olsson FCONF_GET_PROPERTY(hw_config, ethosn_device, dev_idx) 3276a21174SMikael Olsson 3376a21174SMikael Olsson /* NPU core sec registry address */ 3476a21174SMikael Olsson #define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \ 3576a21174SMikael Olsson (core_addr + reg_offset) 3676a21174SMikael Olsson 37e9812ddcSMikael Olsson #define ETHOSN_FW_VA_BASE 0x20000000UL 38e9812ddcSMikael Olsson #define ETHOSN_WORKING_DATA_VA_BASE 0x40000000UL 39e9812ddcSMikael Olsson #define ETHOSN_COMMAND_STREAM_VA_BASE 0x60000000UL 40e9812ddcSMikael Olsson 4176a21174SMikael Olsson /* Reset timeout in us */ 4276a21174SMikael Olsson #define ETHOSN_RESET_TIMEOUT_US U(10 * 1000 * 1000) 4376a21174SMikael Olsson #define ETHOSN_RESET_WAIT_US U(1) 4476a21174SMikael Olsson 457820777fSMikael Olsson #define ETHOSN_AUX_FEAT_LEVEL_IRQ U(0x1) 467820777fSMikael Olsson #define ETHOSN_AUX_FEAT_STASHING U(0x2) 477820777fSMikael Olsson 487820777fSMikael Olsson #define SEC_AUXCTLR_REG U(0x0024) 49*4796d2d9SRob Hughes #define SEC_AUXCTLR_VAL U(0x000ce080) 507820777fSMikael Olsson #define SEC_AUXCTLR_LEVEL_IRQ_VAL U(0x04) 517820777fSMikael Olsson #define SEC_AUXCTLR_STASHING_VAL U(0xA5000000) 527820777fSMikael Olsson 5376a21174SMikael Olsson #define SEC_DEL_REG U(0x0004) 54352366edSRajasekaran Kalidoss #if ETHOSN_NPU_TZMP1 556dcf3e77SMikael Olsson #define SEC_DEL_VAL U(0x808) 566dcf3e77SMikael Olsson #else 577820777fSMikael Olsson #define SEC_DEL_VAL U(0x80C) 58352366edSRajasekaran Kalidoss #endif /* ETHOSN_NPU_TZMP1 */ 5976a21174SMikael Olsson #define SEC_DEL_EXCC_MASK U(0x20) 6076a21174SMikael Olsson 6176a21174SMikael Olsson #define SEC_SECCTLR_REG U(0x0010) 625a89947aSMikael Olsson /* Set bit[10] = 1 to workaround erratum 2838783 */ 635a89947aSMikael Olsson #define SEC_SECCTLR_VAL U(0x403) 6476a21174SMikael Olsson 6576a21174SMikael Olsson #define SEC_DEL_ADDR_EXT_REG U(0x201C) 66e64abe7bSMikael Olsson #define SEC_DEL_ADDR_EXT_VAL U(0x1) 6776a21174SMikael Olsson 6876a21174SMikael Olsson #define SEC_SYSCTRL0_REG U(0x0018) 696dcf3e77SMikael Olsson #define SEC_SYSCTRL0_CPU_WAIT U(1) 702a2e3e87SMikael Olsson #define SEC_SYSCTRL0_SLEEPING U(1U << 4) 716dcf3e77SMikael Olsson #define SEC_SYSCTRL0_INITVTOR_MASK U(0x1FFFFF80) 72273cf25cSZingo Andersen #define SEC_SYSCTRL0_SOFT_RESET U(1U << 29) 7376a21174SMikael Olsson #define SEC_SYSCTRL0_HARD_RESET U(1U << 31) 7476a21174SMikael Olsson 757820777fSMikael Olsson #define SEC_SYSCTRL1_REG U(0x001C) 76*4796d2d9SRob Hughes #define SEC_SYSCTRL1_VAL U(0xe0180110) 777820777fSMikael Olsson 7870a296eeSRajasekaran Kalidoss #define SEC_NSAID_REG_BASE U(0x3004) 7970a296eeSRajasekaran Kalidoss #define SEC_NSAID_OFFSET U(0x1000) 8070a296eeSRajasekaran Kalidoss 81b139f1cfSMikael Olsson #define SEC_MMUSID_REG_BASE U(0x3008) 82b139f1cfSMikael Olsson #define SEC_MMUSID_OFFSET U(0x1000) 83b139f1cfSMikael Olsson 84e64abe7bSMikael Olsson #define SEC_ADDR_EXT_REG_BASE U(0x3018) 85e64abe7bSMikael Olsson #define SEC_ADDR_EXT_OFFSET U(0x1000) 86e64abe7bSMikael Olsson #define SEC_ADDR_EXT_SHIFT U(0x14) 87e64abe7bSMikael Olsson #define SEC_ADDR_EXT_MASK U(0x1FFFFE00) 88e64abe7bSMikael Olsson 89e64abe7bSMikael Olsson #define SEC_ATTR_CTLR_REG_BASE U(0x3010) 90e64abe7bSMikael Olsson #define SEC_ATTR_CTLR_OFFSET U(0x1000) 91e64abe7bSMikael Olsson #define SEC_ATTR_CTLR_NUM U(9) 92e64abe7bSMikael Olsson #define SEC_ATTR_CTLR_VAL U(0x1) 93e64abe7bSMikael Olsson 94313b776fSMikael Olsson #define SEC_NPU_ID_REG U(0xF000) 95313b776fSMikael Olsson #define SEC_NPU_ID_ARCH_VER_SHIFT U(0X10) 96313b776fSMikael Olsson 976dcf3e77SMikael Olsson #define FIRMWARE_STREAM_INDEX U(0x0) 98986c4e99SMikael Olsson #define WORKING_STREAM_INDEX U(0x1) 996dcf3e77SMikael Olsson #define PLE_STREAM_INDEX U(0x4) 10070a296eeSRajasekaran Kalidoss #define INPUT_STREAM_INDEX U(0x6) 10170a296eeSRajasekaran Kalidoss #define INTERMEDIATE_STREAM_INDEX U(0x7) 10270a296eeSRajasekaran Kalidoss #define OUTPUT_STREAM_INDEX U(0x8) 10370a296eeSRajasekaran Kalidoss 104e64abe7bSMikael Olsson #define TO_EXTEND_ADDR(addr) \ 105e64abe7bSMikael Olsson ((addr >> SEC_ADDR_EXT_SHIFT) & SEC_ADDR_EXT_MASK) 106e64abe7bSMikael Olsson 107352366edSRajasekaran Kalidoss #if ETHOSN_NPU_TZMP1 108352366edSRajasekaran Kalidoss CASSERT(ETHOSN_NPU_FW_IMAGE_BASE > 0U, assert_ethosn_invalid_fw_image_base); 109313b776fSMikael Olsson static const struct ethosn_big_fw *big_fw; 1106dcf3e77SMikael Olsson 1116dcf3e77SMikael Olsson #define FW_INITVTOR_ADDR(big_fw) \ 1126dcf3e77SMikael Olsson ((ETHOSN_FW_VA_BASE + big_fw->vector_table_offset) & \ 1136dcf3e77SMikael Olsson SEC_SYSCTRL0_INITVTOR_MASK) 1146dcf3e77SMikael Olsson 1156dcf3e77SMikael Olsson #define SYSCTRL0_INITVTOR_ADDR(value) \ 1166dcf3e77SMikael Olsson (value & SEC_SYSCTRL0_INITVTOR_MASK) 1176dcf3e77SMikael Olsson 118352366edSRajasekaran Kalidoss #endif /* ETHOSN_NPU_TZMP1 */ 119313b776fSMikael Olsson 120b139f1cfSMikael Olsson static bool ethosn_get_device_and_core(uintptr_t core_addr, 121b139f1cfSMikael Olsson const struct ethosn_device_t **dev_match, 122b139f1cfSMikael Olsson const struct ethosn_core_t **core_match) 1231c65989eSLaurent Carlier { 124b139f1cfSMikael Olsson uint32_t dev_idx; 125b139f1cfSMikael Olsson uint32_t core_idx; 126b139f1cfSMikael Olsson 127b139f1cfSMikael Olsson for (dev_idx = 0U; dev_idx < ETHOSN_NUM_DEVICES; ++dev_idx) { 128b139f1cfSMikael Olsson const struct ethosn_device_t *dev = ETHOSN_GET_DEVICE(dev_idx); 129b139f1cfSMikael Olsson 130b139f1cfSMikael Olsson for (core_idx = 0U; core_idx < dev->num_cores; ++core_idx) { 131b139f1cfSMikael Olsson const struct ethosn_core_t *core = &(dev->cores[core_idx]); 132b139f1cfSMikael Olsson 133b139f1cfSMikael Olsson if (core->addr == core_addr) { 134b139f1cfSMikael Olsson *dev_match = dev; 135b139f1cfSMikael Olsson *core_match = core; 1361c65989eSLaurent Carlier return true; 1371c65989eSLaurent Carlier } 1381c65989eSLaurent Carlier } 139b139f1cfSMikael Olsson } 1401c65989eSLaurent Carlier 141b139f1cfSMikael Olsson WARN("ETHOSN: Unknown core address given to SMC call.\n"); 1421c65989eSLaurent Carlier return false; 1431c65989eSLaurent Carlier } 1441c65989eSLaurent Carlier 145352366edSRajasekaran Kalidoss #if ETHOSN_NPU_TZMP1 146313b776fSMikael Olsson static uint32_t ethosn_core_read_arch_version(uintptr_t core_addr) 147313b776fSMikael Olsson { 148313b776fSMikael Olsson uint32_t npu_id = mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, 149313b776fSMikael Olsson SEC_NPU_ID_REG)); 150313b776fSMikael Olsson 151313b776fSMikael Olsson return (npu_id >> SEC_NPU_ID_ARCH_VER_SHIFT); 152313b776fSMikael Olsson } 153313b776fSMikael Olsson 15470a296eeSRajasekaran Kalidoss static void ethosn_configure_stream_nsaid(const struct ethosn_core_t *core, 15570a296eeSRajasekaran Kalidoss bool is_protected) 15670a296eeSRajasekaran Kalidoss { 15770a296eeSRajasekaran Kalidoss size_t i; 158352366edSRajasekaran Kalidoss uint32_t streams[9] = {[0 ... 8] = ETHOSN_NPU_NS_RO_DATA_NSAID}; 15970a296eeSRajasekaran Kalidoss 160352366edSRajasekaran Kalidoss streams[FIRMWARE_STREAM_INDEX] = ETHOSN_NPU_PROT_FW_NSAID; 161352366edSRajasekaran Kalidoss streams[PLE_STREAM_INDEX] = ETHOSN_NPU_PROT_FW_NSAID; 1626dcf3e77SMikael Olsson 163352366edSRajasekaran Kalidoss streams[WORKING_STREAM_INDEX] = ETHOSN_NPU_NS_RW_DATA_NSAID; 164986c4e99SMikael Olsson 16570a296eeSRajasekaran Kalidoss if (is_protected) { 166352366edSRajasekaran Kalidoss streams[INPUT_STREAM_INDEX] = ETHOSN_NPU_PROT_RO_DATA_NSAID; 16770a296eeSRajasekaran Kalidoss streams[INTERMEDIATE_STREAM_INDEX] = 168352366edSRajasekaran Kalidoss ETHOSN_NPU_PROT_RW_DATA_NSAID; 169352366edSRajasekaran Kalidoss streams[OUTPUT_STREAM_INDEX] = ETHOSN_NPU_PROT_RW_DATA_NSAID; 170986c4e99SMikael Olsson } else { 171352366edSRajasekaran Kalidoss streams[INPUT_STREAM_INDEX] = ETHOSN_NPU_NS_RO_DATA_NSAID; 172986c4e99SMikael Olsson streams[INTERMEDIATE_STREAM_INDEX] = 173352366edSRajasekaran Kalidoss ETHOSN_NPU_NS_RW_DATA_NSAID; 174352366edSRajasekaran Kalidoss streams[OUTPUT_STREAM_INDEX] = ETHOSN_NPU_NS_RW_DATA_NSAID; 17570a296eeSRajasekaran Kalidoss } 17670a296eeSRajasekaran Kalidoss 17770a296eeSRajasekaran Kalidoss for (i = 0U; i < ARRAY_SIZE(streams); ++i) { 17870a296eeSRajasekaran Kalidoss const uintptr_t reg_addr = SEC_NSAID_REG_BASE + 17970a296eeSRajasekaran Kalidoss (SEC_NSAID_OFFSET * i); 18070a296eeSRajasekaran Kalidoss mmio_write_32(ETHOSN_CORE_SEC_REG(core->addr, reg_addr), 18170a296eeSRajasekaran Kalidoss streams[i]); 18270a296eeSRajasekaran Kalidoss } 18370a296eeSRajasekaran Kalidoss } 1846dcf3e77SMikael Olsson 1856dcf3e77SMikael Olsson static void ethosn_configure_vector_table(uintptr_t core_addr) 1866dcf3e77SMikael Olsson { 1876dcf3e77SMikael Olsson mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG), 1886dcf3e77SMikael Olsson FW_INITVTOR_ADDR(big_fw)); 1896dcf3e77SMikael Olsson } 1906dcf3e77SMikael Olsson 191352366edSRajasekaran Kalidoss #endif /* ETHOSN_NPU_TZMP1 */ 19270a296eeSRajasekaran Kalidoss 1937820777fSMikael Olsson static void ethosn_configure_events(uintptr_t core_addr) 1947820777fSMikael Olsson { 1957820777fSMikael Olsson mmio_write_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL1_REG), SEC_SYSCTRL1_VAL); 1967820777fSMikael Olsson } 1977820777fSMikael Olsson 1987820777fSMikael Olsson static bool ethosn_configure_aux_features(const struct ethosn_device_t *device, 1997820777fSMikael Olsson uintptr_t core_addr, 2007820777fSMikael Olsson uint32_t features) 2017820777fSMikael Olsson { 2027820777fSMikael Olsson uint32_t val = SEC_AUXCTLR_VAL; 2037820777fSMikael Olsson 2047820777fSMikael Olsson if (features & ETHOSN_AUX_FEAT_LEVEL_IRQ) { 2057820777fSMikael Olsson val |= SEC_AUXCTLR_LEVEL_IRQ_VAL; 2067820777fSMikael Olsson } 2077820777fSMikael Olsson 2087820777fSMikael Olsson if (features & ETHOSN_AUX_FEAT_STASHING) { 2097820777fSMikael Olsson /* Stashing can't be used with reserved memory */ 2107820777fSMikael Olsson if (device->has_reserved_memory) { 2117820777fSMikael Olsson return false; 2127820777fSMikael Olsson } 2137820777fSMikael Olsson 2147820777fSMikael Olsson val |= SEC_AUXCTLR_STASHING_VAL; 2157820777fSMikael Olsson } 2167820777fSMikael Olsson 2177820777fSMikael Olsson mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_AUXCTLR_REG), val); 2187820777fSMikael Olsson 2197820777fSMikael Olsson return true; 2207820777fSMikael Olsson } 2217820777fSMikael Olsson 222b139f1cfSMikael Olsson static void ethosn_configure_smmu_streams(const struct ethosn_device_t *device, 223b139f1cfSMikael Olsson const struct ethosn_core_t *core, 224b139f1cfSMikael Olsson uint32_t asset_alloc_idx) 225b139f1cfSMikael Olsson { 226b139f1cfSMikael Olsson const struct ethosn_main_allocator_t *main_alloc = 227b139f1cfSMikael Olsson &(core->main_allocator); 228b139f1cfSMikael Olsson const struct ethosn_asset_allocator_t *asset_alloc = 229b139f1cfSMikael Olsson &(device->asset_allocators[asset_alloc_idx]); 230b139f1cfSMikael Olsson const uint32_t streams[9] = { 231b139f1cfSMikael Olsson main_alloc->firmware.stream_id, 232b139f1cfSMikael Olsson main_alloc->working_data.stream_id, 233b139f1cfSMikael Olsson asset_alloc->command_stream.stream_id, 234b139f1cfSMikael Olsson 0U, /* Not used*/ 235b139f1cfSMikael Olsson main_alloc->firmware.stream_id, 236b139f1cfSMikael Olsson asset_alloc->weight_data.stream_id, 237b139f1cfSMikael Olsson asset_alloc->buffer_data.stream_id, 238b139f1cfSMikael Olsson asset_alloc->intermediate_data.stream_id, 239b139f1cfSMikael Olsson asset_alloc->buffer_data.stream_id 240b139f1cfSMikael Olsson }; 241b139f1cfSMikael Olsson size_t i; 242b139f1cfSMikael Olsson 243b139f1cfSMikael Olsson for (i = 0U; i < ARRAY_SIZE(streams); ++i) { 244b139f1cfSMikael Olsson const uintptr_t reg_addr = SEC_MMUSID_REG_BASE + 245b139f1cfSMikael Olsson (SEC_MMUSID_OFFSET * i); 246b139f1cfSMikael Olsson mmio_write_32(ETHOSN_CORE_SEC_REG(core->addr, reg_addr), 247b139f1cfSMikael Olsson streams[i]); 248b139f1cfSMikael Olsson } 249b139f1cfSMikael Olsson } 250b139f1cfSMikael Olsson 251e64abe7bSMikael Olsson static void ethosn_configure_stream_addr_extends(const struct ethosn_device_t *device, 252e64abe7bSMikael Olsson uintptr_t core_addr) 253e64abe7bSMikael Olsson { 254e64abe7bSMikael Olsson uint32_t addr_extends[3] = { 0 }; 255e64abe7bSMikael Olsson size_t i; 256e64abe7bSMikael Olsson 257e64abe7bSMikael Olsson if (device->has_reserved_memory) { 258e64abe7bSMikael Olsson const uint32_t addr = TO_EXTEND_ADDR(device->reserved_memory_addr); 259e64abe7bSMikael Olsson 260e64abe7bSMikael Olsson addr_extends[0] = addr; 261e64abe7bSMikael Olsson addr_extends[1] = addr; 262e64abe7bSMikael Olsson addr_extends[2] = addr; 263e64abe7bSMikael Olsson } else { 264e64abe7bSMikael Olsson addr_extends[0] = TO_EXTEND_ADDR(ETHOSN_FW_VA_BASE); 265e64abe7bSMikael Olsson addr_extends[1] = TO_EXTEND_ADDR(ETHOSN_WORKING_DATA_VA_BASE); 266e64abe7bSMikael Olsson addr_extends[2] = TO_EXTEND_ADDR(ETHOSN_COMMAND_STREAM_VA_BASE); 267e64abe7bSMikael Olsson } 268e64abe7bSMikael Olsson 269e64abe7bSMikael Olsson for (i = 0U; i < ARRAY_SIZE(addr_extends); ++i) { 270e64abe7bSMikael Olsson const uintptr_t reg_addr = SEC_ADDR_EXT_REG_BASE + 271e64abe7bSMikael Olsson (SEC_ADDR_EXT_OFFSET * i); 272e64abe7bSMikael Olsson mmio_write_32(ETHOSN_CORE_SEC_REG(core_addr, reg_addr), 273e64abe7bSMikael Olsson addr_extends[i]); 274e64abe7bSMikael Olsson } 275e64abe7bSMikael Olsson } 276e64abe7bSMikael Olsson 277e64abe7bSMikael Olsson static void ethosn_configure_stream_attr_ctlr(uintptr_t core_addr) 278e64abe7bSMikael Olsson { 279e64abe7bSMikael Olsson size_t i; 280e64abe7bSMikael Olsson 281e64abe7bSMikael Olsson for (i = 0U; i < SEC_ATTR_CTLR_NUM; ++i) { 282e64abe7bSMikael Olsson const uintptr_t reg_addr = SEC_ATTR_CTLR_REG_BASE + 283e64abe7bSMikael Olsson (SEC_ATTR_CTLR_OFFSET * i); 284e64abe7bSMikael Olsson mmio_write_32(ETHOSN_CORE_SEC_REG(core_addr, reg_addr), 285e64abe7bSMikael Olsson SEC_ATTR_CTLR_VAL); 286e64abe7bSMikael Olsson } 287e64abe7bSMikael Olsson } 288e64abe7bSMikael Olsson 28976a21174SMikael Olsson static void ethosn_delegate_to_ns(uintptr_t core_addr) 29076a21174SMikael Olsson { 29176a21174SMikael Olsson mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG), 29276a21174SMikael Olsson SEC_SECCTLR_VAL); 29376a21174SMikael Olsson 29476a21174SMikael Olsson mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG), 29576a21174SMikael Olsson SEC_DEL_VAL); 29676a21174SMikael Olsson 29776a21174SMikael Olsson mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG), 29876a21174SMikael Olsson SEC_DEL_ADDR_EXT_VAL); 29976a21174SMikael Olsson } 30076a21174SMikael Olsson 3011c65989eSLaurent Carlier static int ethosn_is_sec(uintptr_t core_addr) 30276a21174SMikael Olsson { 3031c65989eSLaurent Carlier if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG)) 30476a21174SMikael Olsson & SEC_DEL_EXCC_MASK) != 0U) { 30576a21174SMikael Olsson return 0; 30676a21174SMikael Olsson } 30776a21174SMikael Olsson 30876a21174SMikael Olsson return 1; 30976a21174SMikael Olsson } 31076a21174SMikael Olsson 3112a2e3e87SMikael Olsson static int ethosn_core_is_sleeping(uintptr_t core_addr) 3122a2e3e87SMikael Olsson { 3132a2e3e87SMikael Olsson const uintptr_t sysctrl0_reg = 3142a2e3e87SMikael Olsson ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG); 3152a2e3e87SMikael Olsson const uint32_t sleeping_mask = SEC_SYSCTRL0_SLEEPING; 3162a2e3e87SMikael Olsson 3172a2e3e87SMikael Olsson return ((mmio_read_32(sysctrl0_reg) & sleeping_mask) == sleeping_mask); 3182a2e3e87SMikael Olsson } 3192a2e3e87SMikael Olsson 32018a6b79cSMikael Olsson static bool ethosn_core_reset(uintptr_t core_addr, bool hard_reset) 32176a21174SMikael Olsson { 32276a21174SMikael Olsson unsigned int timeout; 32376a21174SMikael Olsson const uintptr_t sysctrl0_reg = 32476a21174SMikael Olsson ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG); 32518a6b79cSMikael Olsson const uint32_t reset_val = hard_reset ? SEC_SYSCTRL0_HARD_RESET : 32618a6b79cSMikael Olsson SEC_SYSCTRL0_SOFT_RESET; 32776a21174SMikael Olsson 32876a21174SMikael Olsson mmio_write_32(sysctrl0_reg, reset_val); 32976a21174SMikael Olsson 33076a21174SMikael Olsson /* Wait for reset to complete */ 33176a21174SMikael Olsson for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US; 33276a21174SMikael Olsson timeout += ETHOSN_RESET_WAIT_US) { 33376a21174SMikael Olsson 33476a21174SMikael Olsson if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) { 33576a21174SMikael Olsson break; 33676a21174SMikael Olsson } 33776a21174SMikael Olsson 33876a21174SMikael Olsson udelay(ETHOSN_RESET_WAIT_US); 33976a21174SMikael Olsson } 34076a21174SMikael Olsson 34176a21174SMikael Olsson return timeout < ETHOSN_RESET_TIMEOUT_US; 34276a21174SMikael Olsson } 34376a21174SMikael Olsson 3446dcf3e77SMikael Olsson static int ethosn_core_boot_fw(uintptr_t core_addr) 3456dcf3e77SMikael Olsson { 346352366edSRajasekaran Kalidoss #if ETHOSN_NPU_TZMP1 3476dcf3e77SMikael Olsson const uintptr_t sysctrl0_reg = ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG); 3486dcf3e77SMikael Olsson const uint32_t sysctrl0_val = mmio_read_32(sysctrl0_reg); 3496dcf3e77SMikael Olsson const bool waiting = (sysctrl0_val & SEC_SYSCTRL0_CPU_WAIT); 3506dcf3e77SMikael Olsson 3516dcf3e77SMikael Olsson if (!waiting) { 3526dcf3e77SMikael Olsson WARN("ETHOSN: Firmware is already running.\n"); 3536dcf3e77SMikael Olsson return ETHOSN_INVALID_STATE; 3546dcf3e77SMikael Olsson } 3556dcf3e77SMikael Olsson 3566dcf3e77SMikael Olsson if (SYSCTRL0_INITVTOR_ADDR(sysctrl0_val) != FW_INITVTOR_ADDR(big_fw)) { 3576dcf3e77SMikael Olsson WARN("ETHOSN: Unknown vector table won't boot firmware.\n"); 3586dcf3e77SMikael Olsson return ETHOSN_INVALID_CONFIGURATION; 3596dcf3e77SMikael Olsson } 3606dcf3e77SMikael Olsson 3616dcf3e77SMikael Olsson mmio_clrbits_32(sysctrl0_reg, SEC_SYSCTRL0_CPU_WAIT); 3626dcf3e77SMikael Olsson 3636dcf3e77SMikael Olsson return ETHOSN_SUCCESS; 3646dcf3e77SMikael Olsson #else 3656dcf3e77SMikael Olsson return ETHOSN_NOT_SUPPORTED; 366352366edSRajasekaran Kalidoss #endif /* ETHOSN_NPU_TZMP1 */ 3676dcf3e77SMikael Olsson } 3686dcf3e77SMikael Olsson 36918a6b79cSMikael Olsson static int ethosn_core_full_reset(const struct ethosn_device_t *device, 37018a6b79cSMikael Olsson const struct ethosn_core_t *core, 37118a6b79cSMikael Olsson bool hard_reset, 37218a6b79cSMikael Olsson u_register_t asset_alloc_idx, 3737820777fSMikael Olsson u_register_t is_protected, 3747820777fSMikael Olsson u_register_t aux_features) 37518a6b79cSMikael Olsson { 37618a6b79cSMikael Olsson if (!device->has_reserved_memory && 37718a6b79cSMikael Olsson asset_alloc_idx >= device->num_allocators) { 37818a6b79cSMikael Olsson WARN("ETHOSN: Unknown asset allocator index given to SMC call.\n"); 37918a6b79cSMikael Olsson return ETHOSN_UNKNOWN_ALLOCATOR_IDX; 38018a6b79cSMikael Olsson } 38118a6b79cSMikael Olsson 38218a6b79cSMikael Olsson if (!ethosn_core_reset(core->addr, hard_reset)) { 38318a6b79cSMikael Olsson return ETHOSN_FAILURE; 38418a6b79cSMikael Olsson } 38518a6b79cSMikael Olsson 3867820777fSMikael Olsson if (!ethosn_configure_aux_features(device, core->addr, aux_features)) { 3877820777fSMikael Olsson return ETHOSN_INVALID_CONFIGURATION; 3887820777fSMikael Olsson } 3897820777fSMikael Olsson 3907820777fSMikael Olsson ethosn_configure_events(core->addr); 3917820777fSMikael Olsson 39218a6b79cSMikael Olsson if (!device->has_reserved_memory) { 39318a6b79cSMikael Olsson ethosn_configure_smmu_streams(device, core, asset_alloc_idx); 39418a6b79cSMikael Olsson 395352366edSRajasekaran Kalidoss #if ETHOSN_NPU_TZMP1 39618a6b79cSMikael Olsson ethosn_configure_stream_nsaid(core, is_protected); 397352366edSRajasekaran Kalidoss #endif /* ETHOSN_NPU_TZMP1 */ 39818a6b79cSMikael Olsson } 39918a6b79cSMikael Olsson 400e64abe7bSMikael Olsson ethosn_configure_stream_addr_extends(device, core->addr); 401e64abe7bSMikael Olsson ethosn_configure_stream_attr_ctlr(core->addr); 402e64abe7bSMikael Olsson 403352366edSRajasekaran Kalidoss #if ETHOSN_NPU_TZMP1 4046dcf3e77SMikael Olsson ethosn_configure_vector_table(core->addr); 405352366edSRajasekaran Kalidoss #endif /* ETHOSN_NPU_TZMP1 */ 4066dcf3e77SMikael Olsson 40718a6b79cSMikael Olsson ethosn_delegate_to_ns(core->addr); 40818a6b79cSMikael Olsson 40918a6b79cSMikael Olsson return ETHOSN_SUCCESS; 41018a6b79cSMikael Olsson } 41118a6b79cSMikael Olsson 41218a6b79cSMikael Olsson static uintptr_t ethosn_smc_core_reset_handler(const struct ethosn_device_t *device, 41318a6b79cSMikael Olsson const struct ethosn_core_t *core, 41418a6b79cSMikael Olsson bool hard_reset, 41518a6b79cSMikael Olsson u_register_t asset_alloc_idx, 41618a6b79cSMikael Olsson u_register_t reset_type, 41718a6b79cSMikael Olsson u_register_t is_protected, 4187820777fSMikael Olsson u_register_t aux_features, 41918a6b79cSMikael Olsson void *handle) 42018a6b79cSMikael Olsson { 42118a6b79cSMikael Olsson int ret; 42218a6b79cSMikael Olsson 42318a6b79cSMikael Olsson switch (reset_type) { 42418a6b79cSMikael Olsson case ETHOSN_RESET_TYPE_FULL: 42518a6b79cSMikael Olsson ret = ethosn_core_full_reset(device, core, hard_reset, 4267820777fSMikael Olsson asset_alloc_idx, is_protected, 4277820777fSMikael Olsson aux_features); 42818a6b79cSMikael Olsson break; 42918a6b79cSMikael Olsson case ETHOSN_RESET_TYPE_HALT: 43018a6b79cSMikael Olsson ret = ethosn_core_reset(core->addr, hard_reset) ? ETHOSN_SUCCESS : ETHOSN_FAILURE; 43118a6b79cSMikael Olsson break; 43218a6b79cSMikael Olsson default: 43318a6b79cSMikael Olsson WARN("ETHOSN: Invalid reset type given to SMC call.\n"); 43418a6b79cSMikael Olsson ret = ETHOSN_INVALID_PARAMETER; 43518a6b79cSMikael Olsson break; 43618a6b79cSMikael Olsson } 43718a6b79cSMikael Olsson 43818a6b79cSMikael Olsson SMC_RET1(handle, ret); 43918a6b79cSMikael Olsson } 44018a6b79cSMikael Olsson 44118a6b79cSMikael Olsson static uintptr_t ethosn_smc_core_handler(uint32_t fid, 4421c65989eSLaurent Carlier u_register_t core_addr, 443b139f1cfSMikael Olsson u_register_t asset_alloc_idx, 444fa37d308SJoshua Pimm u_register_t reset_type, 44570a296eeSRajasekaran Kalidoss u_register_t is_protected, 4467820777fSMikael Olsson u_register_t aux_features, 44718a6b79cSMikael Olsson void *handle) 44818a6b79cSMikael Olsson { 44918a6b79cSMikael Olsson bool hard_reset = false; 45018a6b79cSMikael Olsson const struct ethosn_device_t *device = NULL; 45118a6b79cSMikael Olsson const struct ethosn_core_t *core = NULL; 45218a6b79cSMikael Olsson 45318a6b79cSMikael Olsson if (!ethosn_get_device_and_core(core_addr, &device, &core)) { 45418a6b79cSMikael Olsson SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS); 45518a6b79cSMikael Olsson } 45618a6b79cSMikael Olsson 45718a6b79cSMikael Olsson switch (fid) { 45818a6b79cSMikael Olsson case ETHOSN_FNUM_IS_SEC: 45918a6b79cSMikael Olsson SMC_RET1(handle, ethosn_is_sec(core->addr)); 46018a6b79cSMikael Olsson case ETHOSN_FNUM_IS_SLEEPING: 46118a6b79cSMikael Olsson SMC_RET1(handle, ethosn_core_is_sleeping(core->addr)); 46218a6b79cSMikael Olsson case ETHOSN_FNUM_HARD_RESET: 46318a6b79cSMikael Olsson hard_reset = true; 46418a6b79cSMikael Olsson /* Fallthrough */ 46518a6b79cSMikael Olsson case ETHOSN_FNUM_SOFT_RESET: 46618a6b79cSMikael Olsson return ethosn_smc_core_reset_handler(device, core, 46718a6b79cSMikael Olsson hard_reset, 46818a6b79cSMikael Olsson asset_alloc_idx, 46918a6b79cSMikael Olsson reset_type, 47018a6b79cSMikael Olsson is_protected, 4717820777fSMikael Olsson aux_features, 47218a6b79cSMikael Olsson handle); 4736dcf3e77SMikael Olsson case ETHOSN_FNUM_BOOT_FW: 4746dcf3e77SMikael Olsson SMC_RET1(handle, ethosn_core_boot_fw(core->addr)); 47518a6b79cSMikael Olsson default: 47618a6b79cSMikael Olsson WARN("ETHOSN: Unimplemented SMC call: 0x%x\n", fid); 47718a6b79cSMikael Olsson SMC_RET1(handle, SMC_UNK); 47818a6b79cSMikael Olsson } 47918a6b79cSMikael Olsson } 48018a6b79cSMikael Olsson 481e9812ddcSMikael Olsson static uintptr_t ethosn_smc_fw_prop_handler(u_register_t fw_property, 482e9812ddcSMikael Olsson void *handle) 483e9812ddcSMikael Olsson { 484352366edSRajasekaran Kalidoss #if ETHOSN_NPU_TZMP1 485e9812ddcSMikael Olsson switch (fw_property) { 486e9812ddcSMikael Olsson case ETHOSN_FW_PROP_VERSION: 487e9812ddcSMikael Olsson SMC_RET4(handle, ETHOSN_SUCCESS, 488e9812ddcSMikael Olsson big_fw->fw_ver_major, 489e9812ddcSMikael Olsson big_fw->fw_ver_minor, 490e9812ddcSMikael Olsson big_fw->fw_ver_patch); 491e9812ddcSMikael Olsson case ETHOSN_FW_PROP_MEM_INFO: 492e9812ddcSMikael Olsson SMC_RET3(handle, ETHOSN_SUCCESS, 493e9812ddcSMikael Olsson ((void *)big_fw) + big_fw->offset, 494e9812ddcSMikael Olsson big_fw->size); 495e9812ddcSMikael Olsson case ETHOSN_FW_PROP_OFFSETS: 496e9812ddcSMikael Olsson SMC_RET3(handle, ETHOSN_SUCCESS, 497e9812ddcSMikael Olsson big_fw->ple_offset, 498e9812ddcSMikael Olsson big_fw->unpriv_stack_offset); 499e9812ddcSMikael Olsson case ETHOSN_FW_PROP_VA_MAP: 500e9812ddcSMikael Olsson SMC_RET4(handle, ETHOSN_SUCCESS, 501e9812ddcSMikael Olsson ETHOSN_FW_VA_BASE, 502e9812ddcSMikael Olsson ETHOSN_WORKING_DATA_VA_BASE, 503e9812ddcSMikael Olsson ETHOSN_COMMAND_STREAM_VA_BASE); 504e9812ddcSMikael Olsson default: 505e9812ddcSMikael Olsson WARN("ETHOSN: Unknown firmware property\n"); 506e9812ddcSMikael Olsson SMC_RET1(handle, ETHOSN_INVALID_PARAMETER); 507e9812ddcSMikael Olsson } 508e9812ddcSMikael Olsson #else 509e9812ddcSMikael Olsson SMC_RET1(handle, ETHOSN_NOT_SUPPORTED); 510352366edSRajasekaran Kalidoss #endif /* ETHOSN_NPU_TZMP1 */ 511e9812ddcSMikael Olsson } 512e9812ddcSMikael Olsson 51318a6b79cSMikael Olsson uintptr_t ethosn_smc_handler(uint32_t smc_fid, 51418a6b79cSMikael Olsson u_register_t x1, 51518a6b79cSMikael Olsson u_register_t x2, 51618a6b79cSMikael Olsson u_register_t x3, 51718a6b79cSMikael Olsson u_register_t x4, 51876a21174SMikael Olsson void *cookie, 51976a21174SMikael Olsson void *handle, 52076a21174SMikael Olsson u_register_t flags) 52176a21174SMikael Olsson { 5221c65989eSLaurent Carlier const uint32_t fid = smc_fid & FUNCID_NUM_MASK; 52376a21174SMikael Olsson 52476a21174SMikael Olsson /* Only SiP fast calls are expected */ 52576a21174SMikael Olsson if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) || 52676a21174SMikael Olsson (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) { 52776a21174SMikael Olsson SMC_RET1(handle, SMC_UNK); 52876a21174SMikael Olsson } 52976a21174SMikael Olsson 53076a21174SMikael Olsson /* Truncate parameters to 32-bits for SMC32 */ 53176a21174SMikael Olsson if (GET_SMC_CC(smc_fid) == SMC_32) { 53218a6b79cSMikael Olsson x1 &= 0xFFFFFFFF; 53318a6b79cSMikael Olsson x2 &= 0xFFFFFFFF; 53418a6b79cSMikael Olsson x3 &= 0xFFFFFFFF; 53518a6b79cSMikael Olsson x4 &= 0xFFFFFFFF; 53676a21174SMikael Olsson } 53776a21174SMikael Olsson 5386dcf3e77SMikael Olsson if (!is_ethosn_fid(smc_fid) || (fid > ETHOSN_FNUM_BOOT_FW)) { 539b139f1cfSMikael Olsson WARN("ETHOSN: Unknown SMC call: 0x%x\n", smc_fid); 54076a21174SMikael Olsson SMC_RET1(handle, SMC_UNK); 54176a21174SMikael Olsson } 54276a21174SMikael Olsson 543e9812ddcSMikael Olsson switch (fid) { 544e9812ddcSMikael Olsson case ETHOSN_FNUM_VERSION: 54576a21174SMikael Olsson SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR); 546e9812ddcSMikael Olsson case ETHOSN_FNUM_GET_FW_PROP: 547e9812ddcSMikael Olsson return ethosn_smc_fw_prop_handler(x1, handle); 5481c65989eSLaurent Carlier } 5491c65989eSLaurent Carlier 5507820777fSMikael Olsson return ethosn_smc_core_handler(fid, x1, x2, x3, x4, 5517820777fSMikael Olsson SMC_GET_GP(handle, CTX_GPREG_X5), 5527820777fSMikael Olsson handle); 55376a21174SMikael Olsson } 554a2cdbb1dSMikael Olsson 555a2cdbb1dSMikael Olsson int ethosn_smc_setup(void) 556a2cdbb1dSMikael Olsson { 557352366edSRajasekaran Kalidoss #if ETHOSN_NPU_TZMP1 558313b776fSMikael Olsson struct ethosn_device_t *dev; 559313b776fSMikael Olsson uint32_t arch_ver; 560352366edSRajasekaran Kalidoss #endif /* ETHOSN_NPU_TZMP1 */ 561313b776fSMikael Olsson 562a2cdbb1dSMikael Olsson if (ETHOSN_NUM_DEVICES == 0U) { 563a2cdbb1dSMikael Olsson ERROR("ETHOSN: No NPU found\n"); 564a2cdbb1dSMikael Olsson return ETHOSN_FAILURE; 565a2cdbb1dSMikael Olsson } 566a2cdbb1dSMikael Olsson 567352366edSRajasekaran Kalidoss #if ETHOSN_NPU_TZMP1 568313b776fSMikael Olsson 569313b776fSMikael Olsson /* Only one NPU core is supported in the TZMP1 setup */ 570313b776fSMikael Olsson if ((ETHOSN_NUM_DEVICES != 1U) || 571313b776fSMikael Olsson (ETHOSN_GET_DEVICE(0U)->num_cores != 1U)) { 572313b776fSMikael Olsson ERROR("ETHOSN: TZMP1 doesn't support multiple NPU cores\n"); 573313b776fSMikael Olsson return ETHOSN_FAILURE; 574313b776fSMikael Olsson } 575313b776fSMikael Olsson 576313b776fSMikael Olsson dev = ETHOSN_GET_DEVICE(0U); 5776dcf3e77SMikael Olsson if (dev->has_reserved_memory) { 5786dcf3e77SMikael Olsson ERROR("ETHOSN: TZMP1 doesn't support using reserved memory\n"); 5796dcf3e77SMikael Olsson return ETHOSN_FAILURE; 5806dcf3e77SMikael Olsson } 5816dcf3e77SMikael Olsson 582313b776fSMikael Olsson arch_ver = ethosn_core_read_arch_version(dev->cores[0U].addr); 583352366edSRajasekaran Kalidoss big_fw = (struct ethosn_big_fw *)ETHOSN_NPU_FW_IMAGE_BASE; 584313b776fSMikael Olsson 585313b776fSMikael Olsson if (!ethosn_big_fw_verify_header(big_fw, arch_ver)) { 586313b776fSMikael Olsson return ETHOSN_FAILURE; 587313b776fSMikael Olsson } 588313b776fSMikael Olsson 589313b776fSMikael Olsson NOTICE("ETHOSN: TZMP1 setup succeeded with firmware version %u.%u.%u\n", 590313b776fSMikael Olsson big_fw->fw_ver_major, big_fw->fw_ver_minor, 591313b776fSMikael Olsson big_fw->fw_ver_patch); 592313b776fSMikael Olsson #else 593313b776fSMikael Olsson NOTICE("ETHOSN: Setup succeeded\n"); 594352366edSRajasekaran Kalidoss #endif /* ETHOSN_NPU_TZMP1 */ 595313b776fSMikael Olsson 596a2cdbb1dSMikael Olsson return 0; 597a2cdbb1dSMikael Olsson } 598