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 /*
18  * Number of Arm Ethos-N NPU (NPU) cores available for a
19  * particular parent device
20  */
21 #define ETHOSN_NUM_CORES \
22 	FCONF_GET_PROPERTY(hw_config, ethosn_config, num_cores)
23 
24 /* Address to an NPU core  */
25 #define ETHOSN_CORE_ADDR(core_idx) \
26 	FCONF_GET_PROPERTY(hw_config, ethosn_core_addr, core_idx)
27 
28 /* NPU core sec registry address */
29 #define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \
30 	(core_addr + reg_offset)
31 
32 /* Reset timeout in us */
33 #define ETHOSN_RESET_TIMEOUT_US		U(10 * 1000 * 1000)
34 #define ETHOSN_RESET_WAIT_US		U(1)
35 
36 #define SEC_DEL_REG			U(0x0004)
37 #define SEC_DEL_VAL			U(0x81C)
38 #define SEC_DEL_EXCC_MASK		U(0x20)
39 
40 #define SEC_SECCTLR_REG			U(0x0010)
41 #define SEC_SECCTLR_VAL			U(0x3)
42 
43 #define SEC_DEL_MMUSID_REG		U(0x2008)
44 #define SEC_DEL_MMUSID_VAL		U(0x3FFFF)
45 
46 #define SEC_DEL_ADDR_EXT_REG		U(0x201C)
47 #define SEC_DEL_ADDR_EXT_VAL		U(0x15)
48 
49 #define SEC_SYSCTRL0_REG		U(0x0018)
50 #define SEC_SYSCTRL0_SOFT_RESET		U(3U << 29)
51 #define SEC_SYSCTRL0_HARD_RESET		U(1U << 31)
52 
ethosn_is_core_addr_valid(uintptr_t core_addr)53 static bool ethosn_is_core_addr_valid(uintptr_t core_addr)
54 {
55 	for (uint32_t core_idx = 0U; core_idx < ETHOSN_NUM_CORES; core_idx++) {
56 		if (ETHOSN_CORE_ADDR(core_idx) == core_addr) {
57 			return true;
58 		}
59 	}
60 
61 	return false;
62 }
63 
ethosn_delegate_to_ns(uintptr_t core_addr)64 static void ethosn_delegate_to_ns(uintptr_t core_addr)
65 {
66 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG),
67 			SEC_SECCTLR_VAL);
68 
69 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG),
70 			SEC_DEL_VAL);
71 
72 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_MMUSID_REG),
73 			SEC_DEL_MMUSID_VAL);
74 
75 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG),
76 			SEC_DEL_ADDR_EXT_VAL);
77 }
78 
ethosn_is_sec(uintptr_t core_addr)79 static int ethosn_is_sec(uintptr_t core_addr)
80 {
81 	if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG))
82 		& SEC_DEL_EXCC_MASK) != 0U) {
83 		return 0;
84 	}
85 
86 	return 1;
87 }
88 
ethosn_reset(uintptr_t core_addr,int hard_reset)89 static bool ethosn_reset(uintptr_t core_addr, int hard_reset)
90 {
91 	unsigned int timeout;
92 	const uintptr_t sysctrl0_reg =
93 		ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG);
94 	const uint32_t reset_val = (hard_reset != 0) ? SEC_SYSCTRL0_HARD_RESET
95 						    : SEC_SYSCTRL0_SOFT_RESET;
96 
97 	mmio_write_32(sysctrl0_reg, reset_val);
98 
99 	/* Wait for reset to complete */
100 	for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US;
101 			   timeout += ETHOSN_RESET_WAIT_US) {
102 
103 		if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) {
104 			break;
105 		}
106 
107 		udelay(ETHOSN_RESET_WAIT_US);
108 	}
109 
110 	return timeout < ETHOSN_RESET_TIMEOUT_US;
111 }
112 
ethosn_smc_handler(uint32_t smc_fid,u_register_t core_addr,u_register_t x2,u_register_t x3,u_register_t x4,void * cookie,void * handle,u_register_t flags)113 uintptr_t ethosn_smc_handler(uint32_t smc_fid,
114 			     u_register_t core_addr,
115 			     u_register_t x2,
116 			     u_register_t x3,
117 			     u_register_t x4,
118 			     void *cookie,
119 			     void *handle,
120 			     u_register_t flags)
121 {
122 	int hard_reset = 0;
123 	const uint32_t fid = smc_fid & FUNCID_NUM_MASK;
124 
125 	/* Only SiP fast calls are expected */
126 	if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) ||
127 		(GET_SMC_OEN(smc_fid) != OEN_SIP_START)) {
128 		SMC_RET1(handle, SMC_UNK);
129 	}
130 
131 	/* Truncate parameters to 32-bits for SMC32 */
132 	if (GET_SMC_CC(smc_fid) == SMC_32) {
133 		core_addr &= 0xFFFFFFFF;
134 		x2 &= 0xFFFFFFFF;
135 		x3 &= 0xFFFFFFFF;
136 		x4 &= 0xFFFFFFFF;
137 	}
138 
139 	if (!is_ethosn_fid(smc_fid)) {
140 		SMC_RET1(handle, SMC_UNK);
141 	}
142 
143 	/* Commands that do not require a valid core address */
144 	switch (fid) {
145 	case ETHOSN_FNUM_VERSION:
146 		SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR);
147 	}
148 
149 	if (!ethosn_is_core_addr_valid(core_addr)) {
150 		WARN("ETHOSN: Unknown core address given to SMC call.\n");
151 		SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS);
152 	}
153 
154 	/* Commands that require a valid addr */
155 	switch (fid) {
156 	case ETHOSN_FNUM_IS_SEC:
157 		SMC_RET1(handle, ethosn_is_sec(core_addr));
158 	case ETHOSN_FNUM_HARD_RESET:
159 		hard_reset = 1;
160 		/* Fallthrough */
161 	case ETHOSN_FNUM_SOFT_RESET:
162 		if (!ethosn_reset(core_addr, hard_reset)) {
163 			SMC_RET1(handle, ETHOSN_FAILURE);
164 		}
165 		ethosn_delegate_to_ns(core_addr);
166 		SMC_RET1(handle, ETHOSN_SUCCESS);
167 	default:
168 		SMC_RET1(handle, SMC_UNK);
169 	}
170 }
171