xref: /rk3399_ARM-atf/drivers/arm/ethosn/ethosn_smc.c (revision e64abe7bdaeed99093ae5b4aab8956a04ff4075a)
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 
20313b776fSMikael Olsson #if ARM_ETHOSN_NPU_TZMP1
21313b776fSMikael Olsson #include "ethosn_big_fw.h"
22313b776fSMikael Olsson #endif
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)
497820777fSMikael Olsson #define SEC_AUXCTLR_VAL			U(0x80)
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)
547820777fSMikael Olsson #define SEC_DEL_VAL			U(0x80C)
5576a21174SMikael Olsson #define SEC_DEL_EXCC_MASK		U(0x20)
5676a21174SMikael Olsson 
5776a21174SMikael Olsson #define SEC_SECCTLR_REG			U(0x0010)
585a89947aSMikael Olsson /* Set bit[10] = 1 to workaround erratum 2838783 */
595a89947aSMikael Olsson #define SEC_SECCTLR_VAL			U(0x403)
6076a21174SMikael Olsson 
6176a21174SMikael Olsson #define SEC_DEL_ADDR_EXT_REG            U(0x201C)
62*e64abe7bSMikael Olsson #define SEC_DEL_ADDR_EXT_VAL            U(0x1)
6376a21174SMikael Olsson 
6476a21174SMikael Olsson #define SEC_SYSCTRL0_REG		U(0x0018)
652a2e3e87SMikael Olsson #define SEC_SYSCTRL0_SLEEPING		U(1U << 4)
6676a21174SMikael Olsson #define SEC_SYSCTRL0_SOFT_RESET		U(3U << 29)
6776a21174SMikael Olsson #define SEC_SYSCTRL0_HARD_RESET		U(1U << 31)
6876a21174SMikael Olsson 
697820777fSMikael Olsson #define SEC_SYSCTRL1_REG		U(0x001C)
707820777fSMikael Olsson #define SEC_SYSCTRL1_VAL		U(0x180110)
717820777fSMikael Olsson 
7270a296eeSRajasekaran Kalidoss #define SEC_NSAID_REG_BASE		U(0x3004)
7370a296eeSRajasekaran Kalidoss #define SEC_NSAID_OFFSET		U(0x1000)
7470a296eeSRajasekaran Kalidoss 
75b139f1cfSMikael Olsson #define SEC_MMUSID_REG_BASE		U(0x3008)
76b139f1cfSMikael Olsson #define SEC_MMUSID_OFFSET		U(0x1000)
77b139f1cfSMikael Olsson 
78*e64abe7bSMikael Olsson #define SEC_ADDR_EXT_REG_BASE		U(0x3018)
79*e64abe7bSMikael Olsson #define SEC_ADDR_EXT_OFFSET		U(0x1000)
80*e64abe7bSMikael Olsson #define SEC_ADDR_EXT_SHIFT		U(0x14)
81*e64abe7bSMikael Olsson #define SEC_ADDR_EXT_MASK		U(0x1FFFFE00)
82*e64abe7bSMikael Olsson 
83*e64abe7bSMikael Olsson #define SEC_ATTR_CTLR_REG_BASE		U(0x3010)
84*e64abe7bSMikael Olsson #define SEC_ATTR_CTLR_OFFSET		U(0x1000)
85*e64abe7bSMikael Olsson #define SEC_ATTR_CTLR_NUM		U(9)
86*e64abe7bSMikael Olsson #define SEC_ATTR_CTLR_VAL		U(0x1)
87*e64abe7bSMikael Olsson 
88313b776fSMikael Olsson #define SEC_NPU_ID_REG			U(0xF000)
89313b776fSMikael Olsson #define SEC_NPU_ID_ARCH_VER_SHIFT	U(0X10)
90313b776fSMikael Olsson 
9170a296eeSRajasekaran Kalidoss #define INPUT_STREAM_INDEX              U(0x6)
9270a296eeSRajasekaran Kalidoss #define INTERMEDIATE_STREAM_INDEX       U(0x7)
9370a296eeSRajasekaran Kalidoss #define OUTPUT_STREAM_INDEX             U(0x8)
9470a296eeSRajasekaran Kalidoss 
95*e64abe7bSMikael Olsson #define TO_EXTEND_ADDR(addr) \
96*e64abe7bSMikael Olsson 	((addr >> SEC_ADDR_EXT_SHIFT) & SEC_ADDR_EXT_MASK)
97*e64abe7bSMikael Olsson 
98313b776fSMikael Olsson #if ARM_ETHOSN_NPU_TZMP1
99313b776fSMikael Olsson CASSERT(ARM_ETHOSN_NPU_FW_IMAGE_BASE > 0U, assert_ethosn_invalid_fw_image_base);
100313b776fSMikael Olsson static const struct ethosn_big_fw *big_fw;
101313b776fSMikael Olsson #endif
102313b776fSMikael Olsson 
103b139f1cfSMikael Olsson static bool ethosn_get_device_and_core(uintptr_t core_addr,
104b139f1cfSMikael Olsson 				       const struct ethosn_device_t **dev_match,
105b139f1cfSMikael Olsson 				       const struct ethosn_core_t **core_match)
1061c65989eSLaurent Carlier {
107b139f1cfSMikael Olsson 	uint32_t dev_idx;
108b139f1cfSMikael Olsson 	uint32_t core_idx;
109b139f1cfSMikael Olsson 
110b139f1cfSMikael Olsson 	for (dev_idx = 0U; dev_idx < ETHOSN_NUM_DEVICES; ++dev_idx) {
111b139f1cfSMikael Olsson 		const struct ethosn_device_t *dev = ETHOSN_GET_DEVICE(dev_idx);
112b139f1cfSMikael Olsson 
113b139f1cfSMikael Olsson 		for (core_idx = 0U; core_idx < dev->num_cores; ++core_idx) {
114b139f1cfSMikael Olsson 			const struct ethosn_core_t *core = &(dev->cores[core_idx]);
115b139f1cfSMikael Olsson 
116b139f1cfSMikael Olsson 			if (core->addr == core_addr) {
117b139f1cfSMikael Olsson 				*dev_match = dev;
118b139f1cfSMikael Olsson 				*core_match = core;
1191c65989eSLaurent Carlier 				return true;
1201c65989eSLaurent Carlier 			}
1211c65989eSLaurent Carlier 		}
122b139f1cfSMikael Olsson 	}
1231c65989eSLaurent Carlier 
124b139f1cfSMikael Olsson 	WARN("ETHOSN: Unknown core address given to SMC call.\n");
1251c65989eSLaurent Carlier 	return false;
1261c65989eSLaurent Carlier }
1271c65989eSLaurent Carlier 
12870a296eeSRajasekaran Kalidoss #if ARM_ETHOSN_NPU_TZMP1
129313b776fSMikael Olsson static uint32_t ethosn_core_read_arch_version(uintptr_t core_addr)
130313b776fSMikael Olsson {
131313b776fSMikael Olsson 	uint32_t npu_id = mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr,
132313b776fSMikael Olsson 							   SEC_NPU_ID_REG));
133313b776fSMikael Olsson 
134313b776fSMikael Olsson 	return (npu_id >> SEC_NPU_ID_ARCH_VER_SHIFT);
135313b776fSMikael Olsson }
136313b776fSMikael Olsson 
13770a296eeSRajasekaran Kalidoss static void ethosn_configure_stream_nsaid(const struct ethosn_core_t *core,
13870a296eeSRajasekaran Kalidoss 					  bool is_protected)
13970a296eeSRajasekaran Kalidoss {
14070a296eeSRajasekaran Kalidoss 	size_t i;
14170a296eeSRajasekaran Kalidoss 	uint32_t streams[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
14270a296eeSRajasekaran Kalidoss 
14370a296eeSRajasekaran Kalidoss 	if (is_protected) {
14470a296eeSRajasekaran Kalidoss 		streams[INPUT_STREAM_INDEX] = ARM_ETHOSN_NPU_PROT_DATA_NSAID;
14570a296eeSRajasekaran Kalidoss 		streams[INTERMEDIATE_STREAM_INDEX] =
14670a296eeSRajasekaran Kalidoss 			ARM_ETHOSN_NPU_PROT_DATA_NSAID;
14770a296eeSRajasekaran Kalidoss 		streams[OUTPUT_STREAM_INDEX] = ARM_ETHOSN_NPU_PROT_DATA_NSAID;
14870a296eeSRajasekaran Kalidoss 	}
14970a296eeSRajasekaran Kalidoss 
15070a296eeSRajasekaran Kalidoss 	for (i = 0U; i < ARRAY_SIZE(streams); ++i) {
15170a296eeSRajasekaran Kalidoss 		const uintptr_t reg_addr = SEC_NSAID_REG_BASE +
15270a296eeSRajasekaran Kalidoss 			(SEC_NSAID_OFFSET * i);
15370a296eeSRajasekaran Kalidoss 		mmio_write_32(ETHOSN_CORE_SEC_REG(core->addr, reg_addr),
15470a296eeSRajasekaran Kalidoss 			      streams[i]);
15570a296eeSRajasekaran Kalidoss 	}
15670a296eeSRajasekaran Kalidoss }
15770a296eeSRajasekaran Kalidoss #endif
15870a296eeSRajasekaran Kalidoss 
1597820777fSMikael Olsson static void ethosn_configure_events(uintptr_t core_addr)
1607820777fSMikael Olsson {
1617820777fSMikael Olsson 	mmio_write_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL1_REG), SEC_SYSCTRL1_VAL);
1627820777fSMikael Olsson }
1637820777fSMikael Olsson 
1647820777fSMikael Olsson static bool ethosn_configure_aux_features(const struct ethosn_device_t *device,
1657820777fSMikael Olsson 					  uintptr_t core_addr,
1667820777fSMikael Olsson 					  uint32_t features)
1677820777fSMikael Olsson {
1687820777fSMikael Olsson 	uint32_t val = SEC_AUXCTLR_VAL;
1697820777fSMikael Olsson 
1707820777fSMikael Olsson 	if (features & ETHOSN_AUX_FEAT_LEVEL_IRQ) {
1717820777fSMikael Olsson 		val |= SEC_AUXCTLR_LEVEL_IRQ_VAL;
1727820777fSMikael Olsson 	}
1737820777fSMikael Olsson 
1747820777fSMikael Olsson 	if (features & ETHOSN_AUX_FEAT_STASHING) {
1757820777fSMikael Olsson 		/* Stashing can't be used with reserved memory */
1767820777fSMikael Olsson 		if (device->has_reserved_memory) {
1777820777fSMikael Olsson 			return false;
1787820777fSMikael Olsson 		}
1797820777fSMikael Olsson 
1807820777fSMikael Olsson 		val |= SEC_AUXCTLR_STASHING_VAL;
1817820777fSMikael Olsson 	}
1827820777fSMikael Olsson 
1837820777fSMikael Olsson 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_AUXCTLR_REG), val);
1847820777fSMikael Olsson 
1857820777fSMikael Olsson 	return true;
1867820777fSMikael Olsson }
1877820777fSMikael Olsson 
188b139f1cfSMikael Olsson static void ethosn_configure_smmu_streams(const struct ethosn_device_t *device,
189b139f1cfSMikael Olsson 					  const struct ethosn_core_t *core,
190b139f1cfSMikael Olsson 					  uint32_t asset_alloc_idx)
191b139f1cfSMikael Olsson {
192b139f1cfSMikael Olsson 	const struct ethosn_main_allocator_t *main_alloc =
193b139f1cfSMikael Olsson 		&(core->main_allocator);
194b139f1cfSMikael Olsson 	const struct ethosn_asset_allocator_t *asset_alloc =
195b139f1cfSMikael Olsson 		&(device->asset_allocators[asset_alloc_idx]);
196b139f1cfSMikael Olsson 	const uint32_t streams[9] = {
197b139f1cfSMikael Olsson 		main_alloc->firmware.stream_id,
198b139f1cfSMikael Olsson 		main_alloc->working_data.stream_id,
199b139f1cfSMikael Olsson 		asset_alloc->command_stream.stream_id,
200b139f1cfSMikael Olsson 		0U, /* Not used*/
201b139f1cfSMikael Olsson 		main_alloc->firmware.stream_id,
202b139f1cfSMikael Olsson 		asset_alloc->weight_data.stream_id,
203b139f1cfSMikael Olsson 		asset_alloc->buffer_data.stream_id,
204b139f1cfSMikael Olsson 		asset_alloc->intermediate_data.stream_id,
205b139f1cfSMikael Olsson 		asset_alloc->buffer_data.stream_id
206b139f1cfSMikael Olsson 	};
207b139f1cfSMikael Olsson 	size_t i;
208b139f1cfSMikael Olsson 
209b139f1cfSMikael Olsson 	for (i = 0U; i < ARRAY_SIZE(streams); ++i) {
210b139f1cfSMikael Olsson 		const uintptr_t reg_addr = SEC_MMUSID_REG_BASE +
211b139f1cfSMikael Olsson 			(SEC_MMUSID_OFFSET * i);
212b139f1cfSMikael Olsson 		mmio_write_32(ETHOSN_CORE_SEC_REG(core->addr, reg_addr),
213b139f1cfSMikael Olsson 			      streams[i]);
214b139f1cfSMikael Olsson 	}
215b139f1cfSMikael Olsson }
216b139f1cfSMikael Olsson 
217*e64abe7bSMikael Olsson static void ethosn_configure_stream_addr_extends(const struct ethosn_device_t *device,
218*e64abe7bSMikael Olsson 						 uintptr_t core_addr)
219*e64abe7bSMikael Olsson {
220*e64abe7bSMikael Olsson 	uint32_t addr_extends[3] = { 0 };
221*e64abe7bSMikael Olsson 	size_t i;
222*e64abe7bSMikael Olsson 
223*e64abe7bSMikael Olsson 	if (device->has_reserved_memory) {
224*e64abe7bSMikael Olsson 		const uint32_t addr = TO_EXTEND_ADDR(device->reserved_memory_addr);
225*e64abe7bSMikael Olsson 
226*e64abe7bSMikael Olsson 		addr_extends[0] = addr;
227*e64abe7bSMikael Olsson 		addr_extends[1] = addr;
228*e64abe7bSMikael Olsson 		addr_extends[2] = addr;
229*e64abe7bSMikael Olsson 	} else {
230*e64abe7bSMikael Olsson 		addr_extends[0] = TO_EXTEND_ADDR(ETHOSN_FW_VA_BASE);
231*e64abe7bSMikael Olsson 		addr_extends[1] = TO_EXTEND_ADDR(ETHOSN_WORKING_DATA_VA_BASE);
232*e64abe7bSMikael Olsson 		addr_extends[2] = TO_EXTEND_ADDR(ETHOSN_COMMAND_STREAM_VA_BASE);
233*e64abe7bSMikael Olsson 	}
234*e64abe7bSMikael Olsson 
235*e64abe7bSMikael Olsson 	for (i = 0U; i < ARRAY_SIZE(addr_extends); ++i) {
236*e64abe7bSMikael Olsson 		const uintptr_t reg_addr = SEC_ADDR_EXT_REG_BASE +
237*e64abe7bSMikael Olsson 			(SEC_ADDR_EXT_OFFSET * i);
238*e64abe7bSMikael Olsson 		mmio_write_32(ETHOSN_CORE_SEC_REG(core_addr, reg_addr),
239*e64abe7bSMikael Olsson 			      addr_extends[i]);
240*e64abe7bSMikael Olsson 	}
241*e64abe7bSMikael Olsson }
242*e64abe7bSMikael Olsson 
243*e64abe7bSMikael Olsson static void ethosn_configure_stream_attr_ctlr(uintptr_t core_addr)
244*e64abe7bSMikael Olsson {
245*e64abe7bSMikael Olsson 	size_t i;
246*e64abe7bSMikael Olsson 
247*e64abe7bSMikael Olsson 	for (i = 0U; i < SEC_ATTR_CTLR_NUM; ++i) {
248*e64abe7bSMikael Olsson 		const uintptr_t reg_addr = SEC_ATTR_CTLR_REG_BASE +
249*e64abe7bSMikael Olsson 			(SEC_ATTR_CTLR_OFFSET * i);
250*e64abe7bSMikael Olsson 		mmio_write_32(ETHOSN_CORE_SEC_REG(core_addr, reg_addr),
251*e64abe7bSMikael Olsson 			      SEC_ATTR_CTLR_VAL);
252*e64abe7bSMikael Olsson 	}
253*e64abe7bSMikael Olsson }
254*e64abe7bSMikael Olsson 
25576a21174SMikael Olsson static void ethosn_delegate_to_ns(uintptr_t core_addr)
25676a21174SMikael Olsson {
25776a21174SMikael Olsson 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG),
25876a21174SMikael Olsson 			SEC_SECCTLR_VAL);
25976a21174SMikael Olsson 
26076a21174SMikael Olsson 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG),
26176a21174SMikael Olsson 			SEC_DEL_VAL);
26276a21174SMikael Olsson 
26376a21174SMikael Olsson 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG),
26476a21174SMikael Olsson 			SEC_DEL_ADDR_EXT_VAL);
26576a21174SMikael Olsson }
26676a21174SMikael Olsson 
2671c65989eSLaurent Carlier static int ethosn_is_sec(uintptr_t core_addr)
26876a21174SMikael Olsson {
2691c65989eSLaurent Carlier 	if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG))
27076a21174SMikael Olsson 		& SEC_DEL_EXCC_MASK) != 0U) {
27176a21174SMikael Olsson 		return 0;
27276a21174SMikael Olsson 	}
27376a21174SMikael Olsson 
27476a21174SMikael Olsson 	return 1;
27576a21174SMikael Olsson }
27676a21174SMikael Olsson 
2772a2e3e87SMikael Olsson static int ethosn_core_is_sleeping(uintptr_t core_addr)
2782a2e3e87SMikael Olsson {
2792a2e3e87SMikael Olsson 	const uintptr_t sysctrl0_reg =
2802a2e3e87SMikael Olsson 		ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG);
2812a2e3e87SMikael Olsson 	const uint32_t sleeping_mask = SEC_SYSCTRL0_SLEEPING;
2822a2e3e87SMikael Olsson 
2832a2e3e87SMikael Olsson 	return ((mmio_read_32(sysctrl0_reg) & sleeping_mask) == sleeping_mask);
2842a2e3e87SMikael Olsson }
2852a2e3e87SMikael Olsson 
28618a6b79cSMikael Olsson static bool ethosn_core_reset(uintptr_t core_addr, bool hard_reset)
28776a21174SMikael Olsson {
28876a21174SMikael Olsson 	unsigned int timeout;
28976a21174SMikael Olsson 	const uintptr_t sysctrl0_reg =
29076a21174SMikael Olsson 		ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG);
29118a6b79cSMikael Olsson 	const uint32_t reset_val = hard_reset ? SEC_SYSCTRL0_HARD_RESET :
29218a6b79cSMikael Olsson 						SEC_SYSCTRL0_SOFT_RESET;
29376a21174SMikael Olsson 
29476a21174SMikael Olsson 	mmio_write_32(sysctrl0_reg, reset_val);
29576a21174SMikael Olsson 
29676a21174SMikael Olsson 	/* Wait for reset to complete */
29776a21174SMikael Olsson 	for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US;
29876a21174SMikael Olsson 			   timeout += ETHOSN_RESET_WAIT_US) {
29976a21174SMikael Olsson 
30076a21174SMikael Olsson 		if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) {
30176a21174SMikael Olsson 			break;
30276a21174SMikael Olsson 		}
30376a21174SMikael Olsson 
30476a21174SMikael Olsson 		udelay(ETHOSN_RESET_WAIT_US);
30576a21174SMikael Olsson 	}
30676a21174SMikael Olsson 
30776a21174SMikael Olsson 	return timeout < ETHOSN_RESET_TIMEOUT_US;
30876a21174SMikael Olsson }
30976a21174SMikael Olsson 
31018a6b79cSMikael Olsson static int ethosn_core_full_reset(const struct ethosn_device_t *device,
31118a6b79cSMikael Olsson 				  const struct ethosn_core_t *core,
31218a6b79cSMikael Olsson 				  bool hard_reset,
31318a6b79cSMikael Olsson 				  u_register_t asset_alloc_idx,
3147820777fSMikael Olsson 				  u_register_t is_protected,
3157820777fSMikael Olsson 				  u_register_t aux_features)
31618a6b79cSMikael Olsson {
31718a6b79cSMikael Olsson 	if (!device->has_reserved_memory &&
31818a6b79cSMikael Olsson 	    asset_alloc_idx >= device->num_allocators) {
31918a6b79cSMikael Olsson 		WARN("ETHOSN: Unknown asset allocator index given to SMC call.\n");
32018a6b79cSMikael Olsson 		return ETHOSN_UNKNOWN_ALLOCATOR_IDX;
32118a6b79cSMikael Olsson 	}
32218a6b79cSMikael Olsson 
32318a6b79cSMikael Olsson 	if (!ethosn_core_reset(core->addr, hard_reset)) {
32418a6b79cSMikael Olsson 		return ETHOSN_FAILURE;
32518a6b79cSMikael Olsson 	}
32618a6b79cSMikael Olsson 
3277820777fSMikael Olsson 	if (!ethosn_configure_aux_features(device, core->addr, aux_features)) {
3287820777fSMikael Olsson 		return ETHOSN_INVALID_CONFIGURATION;
3297820777fSMikael Olsson 	}
3307820777fSMikael Olsson 
3317820777fSMikael Olsson 	ethosn_configure_events(core->addr);
3327820777fSMikael Olsson 
33318a6b79cSMikael Olsson 	if (!device->has_reserved_memory) {
33418a6b79cSMikael Olsson 		ethosn_configure_smmu_streams(device, core, asset_alloc_idx);
33518a6b79cSMikael Olsson 
33618a6b79cSMikael Olsson #if ARM_ETHOSN_NPU_TZMP1
33718a6b79cSMikael Olsson 		ethosn_configure_stream_nsaid(core, is_protected);
33818a6b79cSMikael Olsson #endif
33918a6b79cSMikael Olsson 	}
34018a6b79cSMikael Olsson 
341*e64abe7bSMikael Olsson 	ethosn_configure_stream_addr_extends(device, core->addr);
342*e64abe7bSMikael Olsson 	ethosn_configure_stream_attr_ctlr(core->addr);
343*e64abe7bSMikael Olsson 
34418a6b79cSMikael Olsson 	ethosn_delegate_to_ns(core->addr);
34518a6b79cSMikael Olsson 
34618a6b79cSMikael Olsson 	return ETHOSN_SUCCESS;
34718a6b79cSMikael Olsson }
34818a6b79cSMikael Olsson 
34918a6b79cSMikael Olsson static uintptr_t ethosn_smc_core_reset_handler(const struct ethosn_device_t *device,
35018a6b79cSMikael Olsson 					       const struct ethosn_core_t *core,
35118a6b79cSMikael Olsson 					       bool hard_reset,
35218a6b79cSMikael Olsson 					       u_register_t asset_alloc_idx,
35318a6b79cSMikael Olsson 					       u_register_t reset_type,
35418a6b79cSMikael Olsson 					       u_register_t is_protected,
3557820777fSMikael Olsson 					       u_register_t aux_features,
35618a6b79cSMikael Olsson 					       void *handle)
35718a6b79cSMikael Olsson {
35818a6b79cSMikael Olsson 	int ret;
35918a6b79cSMikael Olsson 
36018a6b79cSMikael Olsson 	switch (reset_type) {
36118a6b79cSMikael Olsson 	case ETHOSN_RESET_TYPE_FULL:
36218a6b79cSMikael Olsson 		ret = ethosn_core_full_reset(device, core, hard_reset,
3637820777fSMikael Olsson 					     asset_alloc_idx, is_protected,
3647820777fSMikael Olsson 					     aux_features);
36518a6b79cSMikael Olsson 		break;
36618a6b79cSMikael Olsson 	case ETHOSN_RESET_TYPE_HALT:
36718a6b79cSMikael Olsson 		ret = ethosn_core_reset(core->addr, hard_reset) ? ETHOSN_SUCCESS : ETHOSN_FAILURE;
36818a6b79cSMikael Olsson 		break;
36918a6b79cSMikael Olsson 	default:
37018a6b79cSMikael Olsson 		WARN("ETHOSN: Invalid reset type given to SMC call.\n");
37118a6b79cSMikael Olsson 		ret = ETHOSN_INVALID_PARAMETER;
37218a6b79cSMikael Olsson 		break;
37318a6b79cSMikael Olsson 	}
37418a6b79cSMikael Olsson 
37518a6b79cSMikael Olsson 	SMC_RET1(handle, ret);
37618a6b79cSMikael Olsson }
37718a6b79cSMikael Olsson 
37818a6b79cSMikael Olsson static uintptr_t ethosn_smc_core_handler(uint32_t fid,
3791c65989eSLaurent Carlier 					 u_register_t core_addr,
380b139f1cfSMikael Olsson 					 u_register_t asset_alloc_idx,
381fa37d308SJoshua Pimm 					 u_register_t reset_type,
38270a296eeSRajasekaran Kalidoss 					 u_register_t is_protected,
3837820777fSMikael Olsson 					 u_register_t aux_features,
38418a6b79cSMikael Olsson 					 void *handle)
38518a6b79cSMikael Olsson {
38618a6b79cSMikael Olsson 	bool hard_reset = false;
38718a6b79cSMikael Olsson 	const struct ethosn_device_t *device = NULL;
38818a6b79cSMikael Olsson 	const struct ethosn_core_t *core = NULL;
38918a6b79cSMikael Olsson 
39018a6b79cSMikael Olsson 	if (!ethosn_get_device_and_core(core_addr, &device, &core))  {
39118a6b79cSMikael Olsson 		SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS);
39218a6b79cSMikael Olsson 	}
39318a6b79cSMikael Olsson 
39418a6b79cSMikael Olsson 	switch (fid) {
39518a6b79cSMikael Olsson 	case ETHOSN_FNUM_IS_SEC:
39618a6b79cSMikael Olsson 		SMC_RET1(handle, ethosn_is_sec(core->addr));
39718a6b79cSMikael Olsson 	case ETHOSN_FNUM_IS_SLEEPING:
39818a6b79cSMikael Olsson 		SMC_RET1(handle, ethosn_core_is_sleeping(core->addr));
39918a6b79cSMikael Olsson 	case ETHOSN_FNUM_HARD_RESET:
40018a6b79cSMikael Olsson 		hard_reset = true;
40118a6b79cSMikael Olsson 		/* Fallthrough */
40218a6b79cSMikael Olsson 	case ETHOSN_FNUM_SOFT_RESET:
40318a6b79cSMikael Olsson 		return ethosn_smc_core_reset_handler(device, core,
40418a6b79cSMikael Olsson 						     hard_reset,
40518a6b79cSMikael Olsson 						     asset_alloc_idx,
40618a6b79cSMikael Olsson 						     reset_type,
40718a6b79cSMikael Olsson 						     is_protected,
4087820777fSMikael Olsson 						     aux_features,
40918a6b79cSMikael Olsson 						     handle);
41018a6b79cSMikael Olsson 	default:
41118a6b79cSMikael Olsson 		WARN("ETHOSN: Unimplemented SMC call: 0x%x\n", fid);
41218a6b79cSMikael Olsson 		SMC_RET1(handle, SMC_UNK);
41318a6b79cSMikael Olsson 	}
41418a6b79cSMikael Olsson }
41518a6b79cSMikael Olsson 
416e9812ddcSMikael Olsson static uintptr_t ethosn_smc_fw_prop_handler(u_register_t fw_property,
417e9812ddcSMikael Olsson 					    void *handle)
418e9812ddcSMikael Olsson {
419e9812ddcSMikael Olsson #if ARM_ETHOSN_NPU_TZMP1
420e9812ddcSMikael Olsson 	switch (fw_property) {
421e9812ddcSMikael Olsson 	case ETHOSN_FW_PROP_VERSION:
422e9812ddcSMikael Olsson 		SMC_RET4(handle, ETHOSN_SUCCESS,
423e9812ddcSMikael Olsson 			 big_fw->fw_ver_major,
424e9812ddcSMikael Olsson 			 big_fw->fw_ver_minor,
425e9812ddcSMikael Olsson 			 big_fw->fw_ver_patch);
426e9812ddcSMikael Olsson 	case ETHOSN_FW_PROP_MEM_INFO:
427e9812ddcSMikael Olsson 		SMC_RET3(handle, ETHOSN_SUCCESS,
428e9812ddcSMikael Olsson 			 ((void *)big_fw) + big_fw->offset,
429e9812ddcSMikael Olsson 			 big_fw->size);
430e9812ddcSMikael Olsson 	case ETHOSN_FW_PROP_OFFSETS:
431e9812ddcSMikael Olsson 		SMC_RET3(handle, ETHOSN_SUCCESS,
432e9812ddcSMikael Olsson 			 big_fw->ple_offset,
433e9812ddcSMikael Olsson 			 big_fw->unpriv_stack_offset);
434e9812ddcSMikael Olsson 	case ETHOSN_FW_PROP_VA_MAP:
435e9812ddcSMikael Olsson 		SMC_RET4(handle, ETHOSN_SUCCESS,
436e9812ddcSMikael Olsson 			 ETHOSN_FW_VA_BASE,
437e9812ddcSMikael Olsson 			 ETHOSN_WORKING_DATA_VA_BASE,
438e9812ddcSMikael Olsson 			 ETHOSN_COMMAND_STREAM_VA_BASE);
439e9812ddcSMikael Olsson 	default:
440e9812ddcSMikael Olsson 		WARN("ETHOSN: Unknown firmware property\n");
441e9812ddcSMikael Olsson 		SMC_RET1(handle, ETHOSN_INVALID_PARAMETER);
442e9812ddcSMikael Olsson 	}
443e9812ddcSMikael Olsson #else
444e9812ddcSMikael Olsson 	SMC_RET1(handle, ETHOSN_NOT_SUPPORTED);
445e9812ddcSMikael Olsson #endif
446e9812ddcSMikael Olsson }
447e9812ddcSMikael Olsson 
44818a6b79cSMikael Olsson uintptr_t ethosn_smc_handler(uint32_t smc_fid,
44918a6b79cSMikael Olsson 			     u_register_t x1,
45018a6b79cSMikael Olsson 			     u_register_t x2,
45118a6b79cSMikael Olsson 			     u_register_t x3,
45218a6b79cSMikael Olsson 			     u_register_t x4,
45376a21174SMikael Olsson 			     void *cookie,
45476a21174SMikael Olsson 			     void *handle,
45576a21174SMikael Olsson 			     u_register_t flags)
45676a21174SMikael Olsson {
4571c65989eSLaurent Carlier 	const uint32_t fid = smc_fid & FUNCID_NUM_MASK;
45876a21174SMikael Olsson 
45976a21174SMikael Olsson 	/* Only SiP fast calls are expected */
46076a21174SMikael Olsson 	if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) ||
46176a21174SMikael Olsson 		(GET_SMC_OEN(smc_fid) != OEN_SIP_START)) {
46276a21174SMikael Olsson 		SMC_RET1(handle, SMC_UNK);
46376a21174SMikael Olsson 	}
46476a21174SMikael Olsson 
46576a21174SMikael Olsson 	/* Truncate parameters to 32-bits for SMC32 */
46676a21174SMikael Olsson 	if (GET_SMC_CC(smc_fid) == SMC_32) {
46718a6b79cSMikael Olsson 		x1 &= 0xFFFFFFFF;
46818a6b79cSMikael Olsson 		x2 &= 0xFFFFFFFF;
46918a6b79cSMikael Olsson 		x3 &= 0xFFFFFFFF;
47018a6b79cSMikael Olsson 		x4 &= 0xFFFFFFFF;
47176a21174SMikael Olsson 	}
47276a21174SMikael Olsson 
473e9812ddcSMikael Olsson 	if (!is_ethosn_fid(smc_fid) || (fid > ETHOSN_FNUM_GET_FW_PROP)) {
474b139f1cfSMikael Olsson 		WARN("ETHOSN: Unknown SMC call: 0x%x\n", smc_fid);
47576a21174SMikael Olsson 		SMC_RET1(handle, SMC_UNK);
47676a21174SMikael Olsson 	}
47776a21174SMikael Olsson 
478e9812ddcSMikael Olsson 	switch (fid) {
479e9812ddcSMikael Olsson 	case ETHOSN_FNUM_VERSION:
48076a21174SMikael Olsson 		SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR);
481e9812ddcSMikael Olsson 	case ETHOSN_FNUM_GET_FW_PROP:
482e9812ddcSMikael Olsson 		return ethosn_smc_fw_prop_handler(x1, handle);
4831c65989eSLaurent Carlier 	}
4841c65989eSLaurent Carlier 
4857820777fSMikael Olsson 	return ethosn_smc_core_handler(fid, x1, x2, x3, x4,
4867820777fSMikael Olsson 				       SMC_GET_GP(handle, CTX_GPREG_X5),
4877820777fSMikael Olsson 				       handle);
48876a21174SMikael Olsson }
489a2cdbb1dSMikael Olsson 
490a2cdbb1dSMikael Olsson int ethosn_smc_setup(void)
491a2cdbb1dSMikael Olsson {
492313b776fSMikael Olsson #if ARM_ETHOSN_NPU_TZMP1
493313b776fSMikael Olsson 	struct ethosn_device_t *dev;
494313b776fSMikael Olsson 	uint32_t arch_ver;
495313b776fSMikael Olsson #endif
496313b776fSMikael Olsson 
497a2cdbb1dSMikael Olsson 	if (ETHOSN_NUM_DEVICES == 0U) {
498a2cdbb1dSMikael Olsson 		ERROR("ETHOSN: No NPU found\n");
499a2cdbb1dSMikael Olsson 		return ETHOSN_FAILURE;
500a2cdbb1dSMikael Olsson 	}
501a2cdbb1dSMikael Olsson 
502313b776fSMikael Olsson #if ARM_ETHOSN_NPU_TZMP1
503313b776fSMikael Olsson 
504313b776fSMikael Olsson 	/* Only one NPU core is supported in the TZMP1 setup */
505313b776fSMikael Olsson 	if ((ETHOSN_NUM_DEVICES != 1U) ||
506313b776fSMikael Olsson 	    (ETHOSN_GET_DEVICE(0U)->num_cores != 1U)) {
507313b776fSMikael Olsson 		ERROR("ETHOSN: TZMP1 doesn't support multiple NPU cores\n");
508313b776fSMikael Olsson 		return ETHOSN_FAILURE;
509313b776fSMikael Olsson 	}
510313b776fSMikael Olsson 
511313b776fSMikael Olsson 	dev = ETHOSN_GET_DEVICE(0U);
512313b776fSMikael Olsson 	arch_ver = ethosn_core_read_arch_version(dev->cores[0U].addr);
513313b776fSMikael Olsson 	big_fw = (struct ethosn_big_fw *)ARM_ETHOSN_NPU_FW_IMAGE_BASE;
514313b776fSMikael Olsson 
515313b776fSMikael Olsson 	if (!ethosn_big_fw_verify_header(big_fw, arch_ver)) {
516313b776fSMikael Olsson 		return ETHOSN_FAILURE;
517313b776fSMikael Olsson 	}
518313b776fSMikael Olsson 
519313b776fSMikael Olsson 	NOTICE("ETHOSN: TZMP1 setup succeeded with firmware version %u.%u.%u\n",
520313b776fSMikael Olsson 	       big_fw->fw_ver_major, big_fw->fw_ver_minor,
521313b776fSMikael Olsson 	       big_fw->fw_ver_patch);
522313b776fSMikael Olsson #else
523313b776fSMikael Olsson 	NOTICE("ETHOSN: Setup succeeded\n");
524313b776fSMikael Olsson #endif
525313b776fSMikael Olsson 
526a2cdbb1dSMikael Olsson 	return 0;
527a2cdbb1dSMikael Olsson }
528