xref: /rk3399_ARM-atf/drivers/arm/ethosn/ethosn_smc.c (revision 0165ddd7c06fe2d0556865fce89ced8694e3812e)
1 /*
2  * Copyright (c) 2021-2023, 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 <lib/utils_def.h>
16 #include <plat/arm/common/fconf_ethosn_getter.h>
17 
18 /*
19  * Number of Arm(R) Ethos(TM)-N NPU (NPU) devices available
20  */
21 #define ETHOSN_NUM_DEVICES \
22 	FCONF_GET_PROPERTY(hw_config, ethosn_config, num_devices)
23 
24 #define ETHOSN_GET_DEVICE(dev_idx) \
25 	FCONF_GET_PROPERTY(hw_config, ethosn_device, dev_idx)
26 
27 /* NPU core sec registry address */
28 #define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \
29 	(core_addr + reg_offset)
30 
31 /* Reset timeout in us */
32 #define ETHOSN_RESET_TIMEOUT_US		U(10 * 1000 * 1000)
33 #define ETHOSN_RESET_WAIT_US		U(1)
34 
35 #define SEC_DEL_REG			U(0x0004)
36 #define SEC_DEL_VAL			U(0x81C)
37 #define SEC_DEL_EXCC_MASK		U(0x20)
38 
39 #define SEC_SECCTLR_REG			U(0x0010)
40 #define SEC_SECCTLR_VAL			U(0x3)
41 
42 #define SEC_DEL_ADDR_EXT_REG		U(0x201C)
43 #define SEC_DEL_ADDR_EXT_VAL		U(0x15)
44 
45 #define SEC_SYSCTRL0_REG		U(0x0018)
46 #define SEC_SYSCTRL0_SLEEPING		U(1U << 4)
47 #define SEC_SYSCTRL0_SOFT_RESET		U(3U << 29)
48 #define SEC_SYSCTRL0_HARD_RESET		U(1U << 31)
49 
50 #define SEC_MMUSID_REG_BASE		U(0x3008)
51 #define SEC_MMUSID_OFFSET		U(0x1000)
52 
53 static bool ethosn_get_device_and_core(uintptr_t core_addr,
54 				       const struct ethosn_device_t **dev_match,
55 				       const struct ethosn_core_t **core_match)
56 {
57 	uint32_t dev_idx;
58 	uint32_t core_idx;
59 
60 	for (dev_idx = 0U; dev_idx < ETHOSN_NUM_DEVICES; ++dev_idx) {
61 		const struct ethosn_device_t *dev = ETHOSN_GET_DEVICE(dev_idx);
62 
63 		for (core_idx = 0U; core_idx < dev->num_cores; ++core_idx) {
64 			const struct ethosn_core_t *core = &(dev->cores[core_idx]);
65 
66 			if (core->addr == core_addr) {
67 				*dev_match = dev;
68 				*core_match = core;
69 				return true;
70 			}
71 		}
72 	}
73 
74 	WARN("ETHOSN: Unknown core address given to SMC call.\n");
75 	return false;
76 }
77 
78 static void ethosn_configure_smmu_streams(const struct ethosn_device_t *device,
79 					  const struct ethosn_core_t *core,
80 					  uint32_t asset_alloc_idx)
81 {
82 	const struct ethosn_main_allocator_t *main_alloc =
83 		&(core->main_allocator);
84 	const struct ethosn_asset_allocator_t *asset_alloc =
85 		&(device->asset_allocators[asset_alloc_idx]);
86 	const uint32_t streams[9] = {
87 		main_alloc->firmware.stream_id,
88 		main_alloc->working_data.stream_id,
89 		asset_alloc->command_stream.stream_id,
90 		0U, /* Not used*/
91 		main_alloc->firmware.stream_id,
92 		asset_alloc->weight_data.stream_id,
93 		asset_alloc->buffer_data.stream_id,
94 		asset_alloc->intermediate_data.stream_id,
95 		asset_alloc->buffer_data.stream_id
96 	};
97 	size_t i;
98 
99 	for (i = 0U; i < ARRAY_SIZE(streams); ++i) {
100 		const uintptr_t reg_addr = SEC_MMUSID_REG_BASE +
101 			(SEC_MMUSID_OFFSET * i);
102 		mmio_write_32(ETHOSN_CORE_SEC_REG(core->addr, reg_addr),
103 			      streams[i]);
104 	}
105 }
106 
107 static void ethosn_delegate_to_ns(uintptr_t core_addr)
108 {
109 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG),
110 			SEC_SECCTLR_VAL);
111 
112 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG),
113 			SEC_DEL_VAL);
114 
115 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG),
116 			SEC_DEL_ADDR_EXT_VAL);
117 }
118 
119 static int ethosn_is_sec(uintptr_t core_addr)
120 {
121 	if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG))
122 		& SEC_DEL_EXCC_MASK) != 0U) {
123 		return 0;
124 	}
125 
126 	return 1;
127 }
128 
129 static int ethosn_core_is_sleeping(uintptr_t core_addr)
130 {
131 	const uintptr_t sysctrl0_reg =
132 		ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG);
133 	const uint32_t sleeping_mask = SEC_SYSCTRL0_SLEEPING;
134 
135 	return ((mmio_read_32(sysctrl0_reg) & sleeping_mask) == sleeping_mask);
136 }
137 
138 static bool ethosn_reset(uintptr_t core_addr, int hard_reset)
139 {
140 	unsigned int timeout;
141 	const uintptr_t sysctrl0_reg =
142 		ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG);
143 	const uint32_t reset_val = (hard_reset != 0) ? SEC_SYSCTRL0_HARD_RESET
144 						    : SEC_SYSCTRL0_SOFT_RESET;
145 
146 	mmio_write_32(sysctrl0_reg, reset_val);
147 
148 	/* Wait for reset to complete */
149 	for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US;
150 			   timeout += ETHOSN_RESET_WAIT_US) {
151 
152 		if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) {
153 			break;
154 		}
155 
156 		udelay(ETHOSN_RESET_WAIT_US);
157 	}
158 
159 	return timeout < ETHOSN_RESET_TIMEOUT_US;
160 }
161 
162 uintptr_t ethosn_smc_handler(uint32_t smc_fid,
163 			     u_register_t core_addr,
164 			     u_register_t asset_alloc_idx,
165 			     u_register_t reset_type,
166 			     u_register_t x4,
167 			     void *cookie,
168 			     void *handle,
169 			     u_register_t flags)
170 {
171 	int hard_reset = 0;
172 	const struct ethosn_device_t *device = NULL;
173 	const struct ethosn_core_t *core = NULL;
174 	const uint32_t fid = smc_fid & FUNCID_NUM_MASK;
175 
176 	/* Only SiP fast calls are expected */
177 	if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) ||
178 		(GET_SMC_OEN(smc_fid) != OEN_SIP_START)) {
179 		SMC_RET1(handle, SMC_UNK);
180 	}
181 
182 	/* Truncate parameters to 32-bits for SMC32 */
183 	if (GET_SMC_CC(smc_fid) == SMC_32) {
184 		core_addr &= 0xFFFFFFFF;
185 		asset_alloc_idx &= 0xFFFFFFFF;
186 		reset_type &= 0xFFFFFFFF;
187 		x4 &= 0xFFFFFFFF;
188 	}
189 
190 	if (!is_ethosn_fid(smc_fid) || (fid > ETHOSN_FNUM_IS_SLEEPING)) {
191 		WARN("ETHOSN: Unknown SMC call: 0x%x\n", smc_fid);
192 		SMC_RET1(handle, SMC_UNK);
193 	}
194 
195 	/* Commands that do not require a valid core address */
196 	switch (fid) {
197 	case ETHOSN_FNUM_VERSION:
198 		SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR);
199 	}
200 
201 	if (!ethosn_get_device_and_core(core_addr, &device, &core))  {
202 		SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS);
203 	}
204 
205 	/* Commands that require a valid core address */
206 	switch (fid) {
207 	case ETHOSN_FNUM_IS_SEC:
208 		SMC_RET1(handle, ethosn_is_sec(core->addr));
209 	case ETHOSN_FNUM_IS_SLEEPING:
210 		SMC_RET1(handle, ethosn_core_is_sleeping(core->addr));
211 	}
212 
213 	if (!device->has_reserved_memory &&
214 	    asset_alloc_idx >= device->num_allocators) {
215 		WARN("ETHOSN: Unknown asset allocator index given to SMC call.\n");
216 		SMC_RET1(handle, ETHOSN_UNKNOWN_ALLOCATOR_IDX);
217 	}
218 
219 	if (reset_type > ETHOSN_RESET_TYPE_HALT) {
220 		WARN("ETHOSN: Invalid reset type given to SMC call.\n");
221 		SMC_RET1(handle, ETHOSN_INVALID_PARAMETER);
222 	}
223 
224 	/*
225 	 * Commands that require a valid device, reset type,
226 	 * core and asset allocator
227 	 */
228 	switch (fid) {
229 	case ETHOSN_FNUM_HARD_RESET:
230 		hard_reset = 1;
231 		/* Fallthrough */
232 	case ETHOSN_FNUM_SOFT_RESET:
233 		if (!ethosn_reset(core->addr, hard_reset)) {
234 			SMC_RET1(handle, ETHOSN_FAILURE);
235 		}
236 
237 		if (reset_type == ETHOSN_RESET_TYPE_FULL) {
238 			if (!device->has_reserved_memory) {
239 				ethosn_configure_smmu_streams(device, core,
240 							asset_alloc_idx);
241 			}
242 
243 			ethosn_delegate_to_ns(core->addr);
244 		}
245 		SMC_RET1(handle, ETHOSN_SUCCESS);
246 	default:
247 		WARN("ETHOSN: Unimplemented SMC call: 0x%x\n", fid);
248 		SMC_RET1(handle, SMC_UNK);
249 	}
250 }
251