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