xref: /rk3399_ARM-atf/drivers/arm/ethosn/ethosn_smc.c (revision fa37d30856fef6742bd82e4e0a3252a4d0b9e091)
176a21174SMikael Olsson /*
2*fa37d308SJoshua 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 
181c65989eSLaurent Carlier /*
19b139f1cfSMikael Olsson  * Number of Arm(R) Ethos(TM)-N NPU (NPU) devices available
201c65989eSLaurent Carlier  */
21b139f1cfSMikael Olsson #define ETHOSN_NUM_DEVICES \
22b139f1cfSMikael Olsson 	FCONF_GET_PROPERTY(hw_config, ethosn_config, num_devices)
2376a21174SMikael Olsson 
24b139f1cfSMikael Olsson #define ETHOSN_GET_DEVICE(dev_idx) \
25b139f1cfSMikael Olsson 	FCONF_GET_PROPERTY(hw_config, ethosn_device, dev_idx)
2676a21174SMikael Olsson 
2776a21174SMikael Olsson /* NPU core sec registry address */
2876a21174SMikael Olsson #define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \
2976a21174SMikael Olsson 	(core_addr + reg_offset)
3076a21174SMikael Olsson 
3176a21174SMikael Olsson /* Reset timeout in us */
3276a21174SMikael Olsson #define ETHOSN_RESET_TIMEOUT_US		U(10 * 1000 * 1000)
3376a21174SMikael Olsson #define ETHOSN_RESET_WAIT_US		U(1)
3476a21174SMikael Olsson 
3576a21174SMikael Olsson #define SEC_DEL_REG			U(0x0004)
3676a21174SMikael Olsson #define SEC_DEL_VAL			U(0x81C)
3776a21174SMikael Olsson #define SEC_DEL_EXCC_MASK		U(0x20)
3876a21174SMikael Olsson 
3976a21174SMikael Olsson #define SEC_SECCTLR_REG			U(0x0010)
4076a21174SMikael Olsson #define SEC_SECCTLR_VAL			U(0x3)
4176a21174SMikael Olsson 
4276a21174SMikael Olsson #define SEC_DEL_ADDR_EXT_REG		U(0x201C)
4376a21174SMikael Olsson #define SEC_DEL_ADDR_EXT_VAL		U(0x15)
4476a21174SMikael Olsson 
4576a21174SMikael Olsson #define SEC_SYSCTRL0_REG		U(0x0018)
4676a21174SMikael Olsson #define SEC_SYSCTRL0_SOFT_RESET		U(3U << 29)
4776a21174SMikael Olsson #define SEC_SYSCTRL0_HARD_RESET		U(1U << 31)
4876a21174SMikael Olsson 
49b139f1cfSMikael Olsson #define SEC_MMUSID_REG_BASE		U(0x3008)
50b139f1cfSMikael Olsson #define SEC_MMUSID_OFFSET		U(0x1000)
51b139f1cfSMikael Olsson 
52b139f1cfSMikael Olsson static bool ethosn_get_device_and_core(uintptr_t core_addr,
53b139f1cfSMikael Olsson 				       const struct ethosn_device_t **dev_match,
54b139f1cfSMikael Olsson 				       const struct ethosn_core_t **core_match)
551c65989eSLaurent Carlier {
56b139f1cfSMikael Olsson 	uint32_t dev_idx;
57b139f1cfSMikael Olsson 	uint32_t core_idx;
58b139f1cfSMikael Olsson 
59b139f1cfSMikael Olsson 	for (dev_idx = 0U; dev_idx < ETHOSN_NUM_DEVICES; ++dev_idx) {
60b139f1cfSMikael Olsson 		const struct ethosn_device_t *dev = ETHOSN_GET_DEVICE(dev_idx);
61b139f1cfSMikael Olsson 
62b139f1cfSMikael Olsson 		for (core_idx = 0U; core_idx < dev->num_cores; ++core_idx) {
63b139f1cfSMikael Olsson 			const struct ethosn_core_t *core = &(dev->cores[core_idx]);
64b139f1cfSMikael Olsson 
65b139f1cfSMikael Olsson 			if (core->addr == core_addr) {
66b139f1cfSMikael Olsson 				*dev_match = dev;
67b139f1cfSMikael Olsson 				*core_match = core;
681c65989eSLaurent Carlier 				return true;
691c65989eSLaurent Carlier 			}
701c65989eSLaurent Carlier 		}
71b139f1cfSMikael Olsson 	}
721c65989eSLaurent Carlier 
73b139f1cfSMikael Olsson 	WARN("ETHOSN: Unknown core address given to SMC call.\n");
741c65989eSLaurent Carlier 	return false;
751c65989eSLaurent Carlier }
761c65989eSLaurent Carlier 
77b139f1cfSMikael Olsson static void ethosn_configure_smmu_streams(const struct ethosn_device_t *device,
78b139f1cfSMikael Olsson 					  const struct ethosn_core_t *core,
79b139f1cfSMikael Olsson 					  uint32_t asset_alloc_idx)
80b139f1cfSMikael Olsson {
81b139f1cfSMikael Olsson 	const struct ethosn_main_allocator_t *main_alloc =
82b139f1cfSMikael Olsson 		&(core->main_allocator);
83b139f1cfSMikael Olsson 	const struct ethosn_asset_allocator_t *asset_alloc =
84b139f1cfSMikael Olsson 		&(device->asset_allocators[asset_alloc_idx]);
85b139f1cfSMikael Olsson 	const uint32_t streams[9] = {
86b139f1cfSMikael Olsson 		main_alloc->firmware.stream_id,
87b139f1cfSMikael Olsson 		main_alloc->working_data.stream_id,
88b139f1cfSMikael Olsson 		asset_alloc->command_stream.stream_id,
89b139f1cfSMikael Olsson 		0U, /* Not used*/
90b139f1cfSMikael Olsson 		main_alloc->firmware.stream_id,
91b139f1cfSMikael Olsson 		asset_alloc->weight_data.stream_id,
92b139f1cfSMikael Olsson 		asset_alloc->buffer_data.stream_id,
93b139f1cfSMikael Olsson 		asset_alloc->intermediate_data.stream_id,
94b139f1cfSMikael Olsson 		asset_alloc->buffer_data.stream_id
95b139f1cfSMikael Olsson 	};
96b139f1cfSMikael Olsson 	size_t i;
97b139f1cfSMikael Olsson 
98b139f1cfSMikael Olsson 	for (i = 0U; i < ARRAY_SIZE(streams); ++i) {
99b139f1cfSMikael Olsson 		const uintptr_t reg_addr = SEC_MMUSID_REG_BASE +
100b139f1cfSMikael Olsson 			(SEC_MMUSID_OFFSET * i);
101b139f1cfSMikael Olsson 		mmio_write_32(ETHOSN_CORE_SEC_REG(core->addr, reg_addr),
102b139f1cfSMikael Olsson 			      streams[i]);
103b139f1cfSMikael Olsson 	}
104b139f1cfSMikael Olsson }
105b139f1cfSMikael Olsson 
10676a21174SMikael Olsson static void ethosn_delegate_to_ns(uintptr_t core_addr)
10776a21174SMikael Olsson {
10876a21174SMikael Olsson 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG),
10976a21174SMikael Olsson 			SEC_SECCTLR_VAL);
11076a21174SMikael Olsson 
11176a21174SMikael Olsson 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG),
11276a21174SMikael Olsson 			SEC_DEL_VAL);
11376a21174SMikael Olsson 
11476a21174SMikael Olsson 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG),
11576a21174SMikael Olsson 			SEC_DEL_ADDR_EXT_VAL);
11676a21174SMikael Olsson }
11776a21174SMikael Olsson 
1181c65989eSLaurent Carlier static int ethosn_is_sec(uintptr_t core_addr)
11976a21174SMikael Olsson {
1201c65989eSLaurent Carlier 	if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG))
12176a21174SMikael Olsson 		& SEC_DEL_EXCC_MASK) != 0U) {
12276a21174SMikael Olsson 		return 0;
12376a21174SMikael Olsson 	}
12476a21174SMikael Olsson 
12576a21174SMikael Olsson 	return 1;
12676a21174SMikael Olsson }
12776a21174SMikael Olsson 
12876a21174SMikael Olsson static bool ethosn_reset(uintptr_t core_addr, int hard_reset)
12976a21174SMikael Olsson {
13076a21174SMikael Olsson 	unsigned int timeout;
13176a21174SMikael Olsson 	const uintptr_t sysctrl0_reg =
13276a21174SMikael Olsson 		ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG);
13376a21174SMikael Olsson 	const uint32_t reset_val = (hard_reset != 0) ? SEC_SYSCTRL0_HARD_RESET
13476a21174SMikael Olsson 						    : SEC_SYSCTRL0_SOFT_RESET;
13576a21174SMikael Olsson 
13676a21174SMikael Olsson 	mmio_write_32(sysctrl0_reg, reset_val);
13776a21174SMikael Olsson 
13876a21174SMikael Olsson 	/* Wait for reset to complete */
13976a21174SMikael Olsson 	for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US;
14076a21174SMikael Olsson 			   timeout += ETHOSN_RESET_WAIT_US) {
14176a21174SMikael Olsson 
14276a21174SMikael Olsson 		if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) {
14376a21174SMikael Olsson 			break;
14476a21174SMikael Olsson 		}
14576a21174SMikael Olsson 
14676a21174SMikael Olsson 		udelay(ETHOSN_RESET_WAIT_US);
14776a21174SMikael Olsson 	}
14876a21174SMikael Olsson 
14976a21174SMikael Olsson 	return timeout < ETHOSN_RESET_TIMEOUT_US;
15076a21174SMikael Olsson }
15176a21174SMikael Olsson 
15276a21174SMikael Olsson uintptr_t ethosn_smc_handler(uint32_t smc_fid,
1531c65989eSLaurent Carlier 			     u_register_t core_addr,
154b139f1cfSMikael Olsson 			     u_register_t asset_alloc_idx,
155*fa37d308SJoshua Pimm 			     u_register_t reset_type,
15676a21174SMikael Olsson 			     u_register_t x4,
15776a21174SMikael Olsson 			     void *cookie,
15876a21174SMikael Olsson 			     void *handle,
15976a21174SMikael Olsson 			     u_register_t flags)
16076a21174SMikael Olsson {
16176a21174SMikael Olsson 	int hard_reset = 0;
162b139f1cfSMikael Olsson 	const struct ethosn_device_t *device = NULL;
163b139f1cfSMikael Olsson 	const struct ethosn_core_t *core = NULL;
1641c65989eSLaurent Carlier 	const uint32_t fid = smc_fid & FUNCID_NUM_MASK;
16576a21174SMikael Olsson 
16676a21174SMikael Olsson 	/* Only SiP fast calls are expected */
16776a21174SMikael Olsson 	if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) ||
16876a21174SMikael Olsson 		(GET_SMC_OEN(smc_fid) != OEN_SIP_START)) {
16976a21174SMikael Olsson 		SMC_RET1(handle, SMC_UNK);
17076a21174SMikael Olsson 	}
17176a21174SMikael Olsson 
17276a21174SMikael Olsson 	/* Truncate parameters to 32-bits for SMC32 */
17376a21174SMikael Olsson 	if (GET_SMC_CC(smc_fid) == SMC_32) {
1741c65989eSLaurent Carlier 		core_addr &= 0xFFFFFFFF;
175b139f1cfSMikael Olsson 		asset_alloc_idx &= 0xFFFFFFFF;
176*fa37d308SJoshua Pimm 		reset_type &= 0xFFFFFFFF;
17776a21174SMikael Olsson 		x4 &= 0xFFFFFFFF;
17876a21174SMikael Olsson 	}
17976a21174SMikael Olsson 
180b139f1cfSMikael Olsson 	if (!is_ethosn_fid(smc_fid) ||
181b139f1cfSMikael Olsson 	    (fid < ETHOSN_FNUM_VERSION || fid > ETHOSN_FNUM_SOFT_RESET)) {
182b139f1cfSMikael Olsson 		WARN("ETHOSN: Unknown SMC call: 0x%x\n", smc_fid);
18376a21174SMikael Olsson 		SMC_RET1(handle, SMC_UNK);
18476a21174SMikael Olsson 	}
18576a21174SMikael Olsson 
1861c65989eSLaurent Carlier 	/* Commands that do not require a valid core address */
1871c65989eSLaurent Carlier 	switch (fid) {
18876a21174SMikael Olsson 	case ETHOSN_FNUM_VERSION:
18976a21174SMikael Olsson 		SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR);
1901c65989eSLaurent Carlier 	}
1911c65989eSLaurent Carlier 
192b139f1cfSMikael Olsson 	if (!ethosn_get_device_and_core(core_addr, &device, &core))  {
1931c65989eSLaurent Carlier 		SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS);
1941c65989eSLaurent Carlier 	}
1951c65989eSLaurent Carlier 
196b139f1cfSMikael Olsson 	/* Commands that require a valid core address */
1971c65989eSLaurent Carlier 	switch (fid) {
19876a21174SMikael Olsson 	case ETHOSN_FNUM_IS_SEC:
199b139f1cfSMikael Olsson 		SMC_RET1(handle, ethosn_is_sec(core->addr));
200b139f1cfSMikael Olsson 	}
201b139f1cfSMikael Olsson 
202b139f1cfSMikael Olsson 	if (!device->has_reserved_memory &&
203b139f1cfSMikael Olsson 	    asset_alloc_idx >= device->num_allocators) {
204b139f1cfSMikael Olsson 		WARN("ETHOSN: Unknown asset allocator index given to SMC call.\n");
205b139f1cfSMikael Olsson 		SMC_RET1(handle, ETHOSN_UNKNOWN_ALLOCATOR_IDX);
206b139f1cfSMikael Olsson 	}
207b139f1cfSMikael Olsson 
208*fa37d308SJoshua Pimm 	if (reset_type > ETHOSN_RESET_TYPE_HALT) {
209*fa37d308SJoshua Pimm 		WARN("ETHOSN: Invalid reset type given to SMC call.\n");
210*fa37d308SJoshua Pimm 		SMC_RET1(handle, ETHOSN_INVALID_PARAMETER);
211*fa37d308SJoshua Pimm 	}
212*fa37d308SJoshua Pimm 
213*fa37d308SJoshua Pimm 	/*
214*fa37d308SJoshua Pimm 	 * Commands that require a valid device, reset type,
215*fa37d308SJoshua Pimm 	 * core and asset allocator
216*fa37d308SJoshua Pimm 	 */
217b139f1cfSMikael Olsson 	switch (fid) {
21876a21174SMikael Olsson 	case ETHOSN_FNUM_HARD_RESET:
21976a21174SMikael Olsson 		hard_reset = 1;
22076a21174SMikael Olsson 		/* Fallthrough */
22176a21174SMikael Olsson 	case ETHOSN_FNUM_SOFT_RESET:
222b139f1cfSMikael Olsson 		if (!ethosn_reset(core->addr, hard_reset)) {
22376a21174SMikael Olsson 			SMC_RET1(handle, ETHOSN_FAILURE);
22476a21174SMikael Olsson 		}
225b139f1cfSMikael Olsson 
226*fa37d308SJoshua Pimm 		if (reset_type == ETHOSN_RESET_TYPE_FULL) {
227b139f1cfSMikael Olsson 			if (!device->has_reserved_memory) {
228b139f1cfSMikael Olsson 				ethosn_configure_smmu_streams(device, core,
229b139f1cfSMikael Olsson 							asset_alloc_idx);
230b139f1cfSMikael Olsson 			}
231b139f1cfSMikael Olsson 
232b139f1cfSMikael Olsson 			ethosn_delegate_to_ns(core->addr);
233*fa37d308SJoshua Pimm 		}
23476a21174SMikael Olsson 		SMC_RET1(handle, ETHOSN_SUCCESS);
23576a21174SMikael Olsson 	default:
236b139f1cfSMikael Olsson 		WARN("ETHOSN: Unimplemented SMC call: 0x%x\n", fid);
23776a21174SMikael Olsson 		SMC_RET1(handle, SMC_UNK);
23876a21174SMikael Olsson 	}
23976a21174SMikael Olsson }
240