blob: 60364cdb27ffe557e0cf79f5a71e290fb1452ab1 [file] [log] [blame]
Mikael Olsson7da66192021-02-12 17:30:22 +01001/*
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
Laurent Carlier5205df22021-09-16 15:10:35 +010017/*
18 * Number of Arm Ethos-N NPU (NPU) cores available for a
19 * particular parent device
20 */
Mikael Olsson7da66192021-02-12 17:30:22 +010021#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
Laurent Carlier5205df22021-09-16 15:10:35 +010053static 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
Mikael Olsson7da66192021-02-12 17:30:22 +010064static 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
Laurent Carlier5205df22021-09-16 15:10:35 +010079static int ethosn_is_sec(uintptr_t core_addr)
Mikael Olsson7da66192021-02-12 17:30:22 +010080{
Laurent Carlier5205df22021-09-16 15:10:35 +010081 if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG))
Mikael Olsson7da66192021-02-12 17:30:22 +010082 & SEC_DEL_EXCC_MASK) != 0U) {
83 return 0;
84 }
85
86 return 1;
87}
88
89static 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
113uintptr_t ethosn_smc_handler(uint32_t smc_fid,
Laurent Carlier5205df22021-09-16 15:10:35 +0100114 u_register_t core_addr,
Mikael Olsson7da66192021-02-12 17:30:22 +0100115 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{
Mikael Olsson7da66192021-02-12 17:30:22 +0100122 int hard_reset = 0;
Laurent Carlier5205df22021-09-16 15:10:35 +0100123 const uint32_t fid = smc_fid & FUNCID_NUM_MASK;
Mikael Olsson7da66192021-02-12 17:30:22 +0100124
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) {
Laurent Carlier5205df22021-09-16 15:10:35 +0100133 core_addr &= 0xFFFFFFFF;
Mikael Olsson7da66192021-02-12 17:30:22 +0100134 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
Laurent Carlier5205df22021-09-16 15:10:35 +0100143 /* Commands that do not require a valid core address */
144 switch (fid) {
Mikael Olsson7da66192021-02-12 17:30:22 +0100145 case ETHOSN_FNUM_VERSION:
146 SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR);
Laurent Carlier5205df22021-09-16 15:10:35 +0100147 }
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) {
Mikael Olsson7da66192021-02-12 17:30:22 +0100156 case ETHOSN_FNUM_IS_SEC:
Laurent Carlier5205df22021-09-16 15:10:35 +0100157 SMC_RET1(handle, ethosn_is_sec(core_addr));
Mikael Olsson7da66192021-02-12 17:30:22 +0100158 case ETHOSN_FNUM_HARD_RESET:
159 hard_reset = 1;
160 /* Fallthrough */
161 case ETHOSN_FNUM_SOFT_RESET:
Mikael Olsson7da66192021-02-12 17:30:22 +0100162 if (!ethosn_reset(core_addr, hard_reset)) {
163 SMC_RET1(handle, ETHOSN_FAILURE);
164 }
Mikael Olsson7da66192021-02-12 17:30:22 +0100165 ethosn_delegate_to_ns(core_addr);
Mikael Olsson7da66192021-02-12 17:30:22 +0100166 SMC_RET1(handle, ETHOSN_SUCCESS);
167 default:
168 SMC_RET1(handle, SMC_UNK);
169 }
170}