xref: /rk3399_ARM-atf/drivers/arm/ethosn/ethosn_smc.c (revision 1c65989e70c9734defc666e824628620b2060b92)
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