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