1 /*
2 * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2009-12-22
13 * Description: UniProton hi3093 demo
14 */
15 #include "securec.h"
16 #include "prt_tick.h"
17 #include "prt_hwi.h"
18 #include "prt_sys.h"
19 #include "prt_task.h"
20 #include "cpu_config.h"
21
22 #if (OS_GIC_VER == 3)
23 enum GicIntState {
24 GIC_DISABLE = 0,
25 GIC_ENABLE = 1
26 };
27
28 enum SicGroupType {
29 SIC_GROUP_G0S = 0,
30 SIC_GROUP_G1NS = 1,
31 SIC_GROUP_G1S = 2,
32 SIC_GROUP_BUTT,
33 };
34
35 union SicrWaker {
36 struct {
37 U32 res0 : 1;
38 U32 sleepReq : 1;
39 U32 isSleep : 1;
40 U32 res1 : 29;
41 } bits;
42 U32 value;
43 };
44
45 union SicrCtrl {
46 struct {
47 U32 enLpis : 1;
48 U32 res2 : 2;
49 U32 rwp : 1;
50 U32 res1 : 20;
51 U32 dpg0 : 1;
52 U32 dpg1ns : 1;
53 U32 dpg1s : 1;
54 U32 res0 : 4;
55 U32 uwp : 1;
56 } bits;
57 U32 value;
58 };
59
60 union HwiIccSreElx {
61 struct {
62 U64 prt : 1;
63 U64 dfb : 1;
64 U64 dib : 1;
65 U64 enable : 1;
66 U64 res : 60;
67 } bits;
68 U64 value;
69 };
70
71 union SicdCtrl {
72 struct {
73 U32 enG0S : 1;
74 U32 enG1Ns : 1;
75 U32 enG1S : 1;
76 U32 res1 : 1;
77 U32 areS : 1;
78 U32 areNs : 1;
79 U32 ds : 1;
80 U32 res0 : 24;
81 U32 rwp : 1;
82 } bits;
83 U32 value;
84 };
85
86 extern void OsGicdWaitCfgWork();
87
OsSicrInit(void)88 void OsSicrInit(void)
89 {
90 union SicrWaker sicrWaker;
91 uintptr_t regAddr;
92 U32 intId;
93
94 regAddr = GICR_WAKER_ADDR + OsGetCoreID() * SICR_ADDR_OFFSET_PER_CORE;
95 sicrWaker.value = GIC_REG_READ(regAddr);
96 sicrWaker.bits.sleepReq = 0;
97 GIC_REG_WRITE(regAddr, sicrWaker.value);
98 sicrWaker.value = GIC_REG_READ(regAddr);
99 while (sicrWaker.bits.isSleep == 1) {
100 sicrWaker.value = GIC_REG_READ(regAddr);
101 }
102 }
103
OsSicrSetIntGroup(U32 coreId,U64 intId,enum SicGroupType groupId)104 void OsSicrSetIntGroup(U32 coreId, U64 intId, enum SicGroupType groupId)
105 {
106 uintptr_t group0RegAddr;
107 uintptr_t modRegAddr;
108 U32 group0RegTmp;
109 U32 modRegTmp;
110
111 group0RegAddr = GICR_IGROUPR0_ADDR + OsGetCoreID() * SICR_ADDR_OFFSET_PER_CORE;
112 group0RegTmp = GIC_REG_READ(group0RegAddr);
113
114 if ((groupId == SIC_GROUP_G0S) || (groupId == SIC_GROUP_G1S)) {
115 group0RegTmp &= ~(0x1U << intId);
116 } else {
117 group0RegTmp |= (0x1U << intId);
118 }
119 GIC_REG_WRITE(group0RegAddr, group0RegTmp);
120
121 modRegAddr = GICR_IGRPMODR0_ADDR + OsGetCoreID() * SICR_ADDR_OFFSET_PER_CORE;
122 modRegTmp = GIC_REG_READ(modRegAddr);
123
124 if (groupId == SIC_GROUP_G1S) {
125 modRegTmp |= (0x1U << intId);
126 } else {
127 modRegTmp &= ~(0x1U << intId);
128 }
129 GIC_REG_WRITE(modRegAddr, modRegTmp);
130 }
131
OsSiccEnableSre(void)132 U32 OsSiccEnableSre(void)
133 {
134 volatile union HwiIccSreElx iccSre;
135
136 OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_SRE_EL1) " \n" : "=&r"(iccSre));
137 iccSre.bits.prt = 1;
138 iccSre.bits.dfb = 1;
139 iccSre.bits.dib = 1;
140 OS_EMBED_ASM("MSR " REG_ALIAS(ICC_SRE_EL1) ", %0 \n" : : "r"(iccSre));
141 OS_EMBED_ASM("DSB SY");
142 OS_EMBED_ASM("ISB");
143
144 OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_SRE_EL1) " \n" : "=&r"(iccSre.value));
145
146 if (iccSre.bits.prt != 1) {
147 return OS_FAIL;
148 }
149
150 return OS_OK;
151 }
152
OsSiccCfgIntPreempt(void)153 void OsSiccCfgIntPreempt(void)
154 {
155 U64 tmp = 0;
156
157 OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_BPR1_EL1) " \n" : "=&r"(tmp) : : "memory");
158 tmp &= ~(GROUP_MAX_BPR);
159 tmp |= GROUP1_BP;
160 OS_EMBED_ASM("MSR " REG_ALIAS(ICC_BPR1_EL1) ", %0 \n" : : "r"(tmp) : "memory");
161 }
162
OsSiccEnableGroup1(void)163 void OsSiccEnableGroup1(void)
164 {
165 U64 tmp = 0;
166
167 OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_IGRPEN1_EL1) " \n" : "=&r"(tmp) : : "memory");
168 tmp |= 0x01U;
169 OS_EMBED_ASM("MSR " REG_ALIAS(ICC_IGRPEN1_EL1) ", %0 \n" : : "r"(tmp) : "memory");
170 }
171
OsSiccCfgPriorityMask(void)172 void OsSiccCfgPriorityMask(void)
173 {
174 U64 tmp = 0;
175
176 OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_PMR_EL1) " \n" : "=&r"(tmp) : : "memory");
177 tmp |= PRIO_MASK_LEVEL;
178 OS_EMBED_ASM("MSR " REG_ALIAS(ICC_PMR_EL1) ", %0 \n" : : "r"(tmp) : "memory");
179 }
180
OsSiccInit(void)181 U32 OsSiccInit(void)
182 {
183 U32 ret;
184
185 ret = OsSiccEnableSre();
186 if (ret != OS_OK) {
187 return ret;
188 }
189
190 OsSiccCfgIntPreempt();
191
192 OsSiccEnableGroup1();
193
194 OsSiccCfgPriorityMask();
195
196 return OS_OK;
197 }
198
OsSicdSetIntGroup(U32 intId,enum SicGroupType groupId)199 void OsSicdSetIntGroup(U32 intId, enum SicGroupType groupId)
200 {
201 U64 group0RegAddr;
202 U64 modRegAddr;
203 U32 group0RegTmp;
204 U32 modRegTmp;
205 U32 sicdM;
206 U32 bitOffset;
207
208 sicdM = (intId - MIN_GIC_SPI_NUM) / SICD_IGROUP_INT_NUM;
209 group0RegAddr = GICD_IGROUPN_ADDR + (SICD_REG_SIZE * sicdM);
210 modRegAddr = GICD_IGRPMODRN_ADDR + (SICD_REG_SIZE * sicdM);
211 bitOffset = (intId - MIN_GIC_SPI_NUM) % SICD_IGROUP_INT_NUM;
212
213 group0RegTmp = GIC_REG_READ(group0RegAddr);
214 if ((groupId == SIC_GROUP_G0S) || (groupId == SIC_GROUP_G1S)) {
215 group0RegTmp &= ~(0x1U << bitOffset);
216 } else {
217 group0RegTmp |= (0x1U << bitOffset);
218 }
219 GIC_REG_WRITE(group0RegAddr, group0RegTmp);
220
221 modRegTmp = GIC_REG_READ(modRegAddr);
222 if (groupId == SIC_GROUP_G1S) {
223 modRegTmp |= (0x1U << bitOffset);
224 } else {
225 modRegTmp &= ~(0x1U << bitOffset);
226 }
227 GIC_REG_WRITE(modRegAddr, modRegTmp);
228 }
229
OsSicSetGroup(U32 intId,enum SicGroupType groupId)230 void OsSicSetGroup(U32 intId, enum SicGroupType groupId)
231 {
232 U32 coreId = OsGetCoreID();
233 enum GicIntState state;
234
235 if (intId < MIN_GIC_SPI_NUM) {
236 state = OsGicrGetIntState(coreId, intId);
237 OsGicrDisableInt(coreId, intId);
238 OsSicrSetIntGroup(coreId, intId, groupId);
239 if (state == GIC_ENABLE) {
240 OsGicrEnableInt(coreId, intId);
241 }
242 } else {
243 state = OsGicdGetIntState(intId);
244 OsGicdDisableInt(intId);
245 OsSicdSetIntGroup(intId, groupId);
246 if (state == GIC_ENABLE) {
247 OsGicdEnableInt(intId);
248 }
249 }
250 }
251
OsSicInitLocal(void)252 U32 OsSicInitLocal(void)
253 {
254 U32 ret;
255 U32 intId;
256
257 OsSicrInit();
258
259 ret = OsSiccInit();
260 if (ret != OS_OK) {
261 return ret;
262 }
263
264 for (intId = 0; intId < MIN_GIC_SPI_NUM; ++intId) {
265 OsSicSetGroup(intId, SIC_GROUP_G1NS);
266 }
267
268 return OS_OK;
269 }
270
OsSicdInit(void)271 void OsSicdInit(void)
272 {
273 union SicdCtrl sicdCtrl;
274
275 sicdCtrl.value = GIC_REG_READ(GICD_CTLR_S_ADDR);
276
277 if ((sicdCtrl.bits.enG0S == 1) || (sicdCtrl.bits.enG1Ns == 1) || (sicdCtrl.bits.enG1S == 1)) {
278 return;
279 }
280
281 sicdCtrl.bits.ds = 0;
282 sicdCtrl.bits.areNs = 1;
283 sicdCtrl.bits.areS = 1;
284 sicdCtrl.bits.enG1Ns = 1;
285 GIC_REG_WRITE(GICD_CTLR_S_ADDR, sicdCtrl.value);
286
287 OsGicdWaitCfgWork();
288 }
289
OsSicInitGlobal(void)290 void OsSicInitGlobal(void)
291 {
292 U32 intId;
293
294 OsSicdInit();
295
296 for (intId = MIN_GIC_SPI_NUM; intId < MAX_INT_NUM; ++intId) {
297 OsSicSetGroup(intId, SIC_GROUP_G1NS);
298 }
299 }
300 #elif (OS_GIC_VER == 2)
IsrRegister(U32 intNo,U32 pri)301 int IsrRegister(U32 intNo, U32 pri)
302 {
303 U32 bitn, reg, shift;
304 U32 *addr;
305
306 bitn = intNo / 32U;
307 addr = (U32 *)(GICD_ISENABLERn + 4U * bitn);
308 reg = *addr;
309 *addr = (reg | (0x1U << (intNo % 32U)));
310
311 bitn = intNo / 4U;
312 addr = (U32 *)(GICD_IPRIORITYn + 4U * bitn);
313 shift = (intNo % 4U) * 8U;
314 reg = (*addr) & ~(0xFFU << shift);
315 *addr = (reg | pri << shift);
316 }
317
OsGicInitCpuInterface(void)318 void OsGicInitCpuInterface(void)
319 {
320 int i;
321 U32 val;
322
323 GIC_REG_WRITE(0xFFFFFFFF, GICD_ICACTIVERn);
324 GIC_REG_WRITE(0xFFFF0000, GICD_ICENABLERn);
325 GIC_REG_WRITE(0x0000FFFF, GICD_ISENABLERn);
326
327 for (i = 0; i < 32; i += 4) {
328 GIC_REG_WRITE(0xA0A0A0A0, GICD_IPRIORITYn + i);
329 }
330
331 GIC_REG_WRITE(0xF0, GICC_PMR);
332 val = GIC_REG_READ(GICC_CTLR);
333 val &= ~GICC_CTLR_BYPASS_MASK;
334 val |= GICC_CTLR_ENABLE_MASK;
335 GIC_REG_WRITE(val, GICC_CTLR);
336 }
337 #endif
OsHwiInit(void)338 U32 OsHwiInit(void)
339 {
340 #if (OS_GIC_VER == 3)
341 U32 ret;
342
343 ret = OsSicInitLocal();
344 if (ret != OS_OK) {
345 return ret;
346 }
347
348 if(PRT_GetCoreID() == 0) {
349 OsSicInitGlobal();
350 }
351 #elif (OS_GIC_VER == 2)
352 OsGicInitCpuInterface();
353 #endif
354 return OS_OK;
355 }
356