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 raspi4 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
99 sicrWaker.value = GIC_REG_READ(regAddr);
100 while (sicrWaker.bits.isSleep == 1) {
101 sicrWaker.value = GIC_REG_READ(regAddr);
102 }
103 }
104
OsSicrSetIntGroup(U32 coreId,U64 intId,enum SicGroupType groupId)105 void OsSicrSetIntGroup(U32 coreId, U64 intId, enum SicGroupType groupId)
106 {
107 uintptr_t group0RegAddr;
108 uintptr_t modRegAddr;
109 U32 group0RegTmp;
110 U32 modRegTmp;
111
112 group0RegAddr = GICR_IGROUPR0_ADDR + OsGetCoreID() * SICR_ADDR_OFFSET_PER_CORE;
113 group0RegTmp = GIC_REG_READ(group0RegAddr);
114
115 if ((groupId == SIC_GROUP_G0S) || (groupId == SIC_GROUP_G1S)) {
116 group0RegTmp &= ~(0x1U << intId);
117 } else {
118 group0RegTmp |= (0x1U << intId);
119 }
120 GIC_REG_WRITE(group0RegAddr, group0RegTmp);
121
122 modRegAddr = GICR_IGRPMODR0_ADDR + OsGetCoreID() * SICR_ADDR_OFFSET_PER_CORE;
123 modRegTmp = GIC_REG_READ(modRegAddr);
124
125 if (groupId == SIC_GROUP_G1S) {
126 modRegTmp |= (0x1U << intId);
127 } else {
128 modRegTmp &= ~(0x1U << intId);
129 }
130 GIC_REG_WRITE(modRegAddr, modRegTmp);
131 }
132
OsSiccEnableSre(void)133 U32 OsSiccEnableSre(void)
134 {
135 volatile union HwiIccSreElx iccSre;
136
137 OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_SRE_EL1) " \n" : "=&r"(iccSre));
138 iccSre.bits.prt = 1;
139 iccSre.bits.dfb = 1;
140 iccSre.bits.dib = 1;
141 OS_EMBED_ASM("MSR " REG_ALIAS(ICC_SRE_EL1) ", %0 \n" : : "r"(iccSre));
142 OS_EMBED_ASM("DSB SY");
143 OS_EMBED_ASM("ISB");
144
145 OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_SRE_EL1) " \n" : "=&r"(iccSre.value));
146
147 if (iccSre.bits.prt != 1) {
148 return OS_FAIL;
149 }
150
151 return OS_OK;
152 }
153
OsSiccCfgIntPreempt(void)154 void OsSiccCfgIntPreempt(void)
155 {
156 U64 tmp = 0;
157
158 OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_BPR1_EL1) " \n" : "=&r"(tmp) : : "memory");
159 tmp &= ~(GROUP_MAX_BPR);
160 tmp |= GROUP1_BP;
161 OS_EMBED_ASM("MSR " REG_ALIAS(ICC_BPR1_EL1) ", %0 \n" : : "r"(tmp) : "memory");
162 }
163
OsSiccEnableGroup1(void)164 void OsSiccEnableGroup1(void)
165 {
166 U64 tmp = 0;
167
168 OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_IGRPEN1_EL1) " \n" : "=&r"(tmp) : : "memory");
169 tmp |= 0x01U;
170 OS_EMBED_ASM("MSR " REG_ALIAS(ICC_IGRPEN1_EL1) ", %0 \n" : : "r"(tmp) : "memory");
171 }
172
OsSiccCfgPriorityMask(void)173 void OsSiccCfgPriorityMask(void)
174 {
175 U64 tmp = 0;
176
177 OS_EMBED_ASM("MRS %0, " REG_ALIAS(ICC_PMR_EL1) " \n" : "=&r"(tmp) : : "memory");
178 tmp |= PRIO_MASK_LEVEL;
179 OS_EMBED_ASM("MSR " REG_ALIAS(ICC_PMR_EL1) ", %0 \n" : : "r"(tmp) : "memory");
180 }
181
OsSiccInit(void)182 U32 OsSiccInit(void)
183 {
184 U32 ret;
185
186 ret = OsSiccEnableSre();
187 if (ret != OS_OK) {
188 return ret;
189 }
190
191 OsSiccCfgIntPreempt();
192
193 OsSiccEnableGroup1();
194
195 OsSiccCfgPriorityMask();
196
197 return OS_OK;
198 }
199
OsSicdSetIntGroup(U32 intId,enum SicGroupType groupId)200 void OsSicdSetIntGroup(U32 intId, enum SicGroupType groupId)
201 {
202 U64 group0RegAddr;
203 U64 modRegAddr;
204 U32 group0RegTmp;
205 U32 modRegTmp;
206 U32 sicdM;
207 U32 bitOffset;
208
209 sicdM = (intId - MIN_GIC_SPI_NUM) / SICD_IGROUP_INT_NUM;
210 group0RegAddr = GICD_IGROUPN_ADDR + (SICD_REG_SIZE * sicdM);
211 modRegAddr = GICD_IGRPMODRN_ADDR + (SICD_REG_SIZE * sicdM);
212 bitOffset = (intId - MIN_GIC_SPI_NUM) % SICD_IGROUP_INT_NUM;
213
214 group0RegTmp = GIC_REG_READ(group0RegAddr);
215 if ((groupId == SIC_GROUP_G0S) || (groupId == SIC_GROUP_G1S)) {
216 group0RegTmp &= ~(0x1U << bitOffset);
217 } else {
218 group0RegTmp |= (0x1U << bitOffset);
219 }
220 GIC_REG_WRITE(group0RegAddr, group0RegTmp);
221
222 modRegTmp = GIC_REG_READ(modRegAddr);
223 if (groupId == SIC_GROUP_G1S) {
224 modRegTmp |= (0x1U << bitOffset);
225 } else {
226 modRegTmp &= ~(0x1U << bitOffset);
227 }
228 GIC_REG_WRITE(modRegAddr, modRegTmp);
229 }
230
OsSicSetGroup(U32 intId,enum SicGroupType groupId)231 void OsSicSetGroup(U32 intId, enum SicGroupType groupId)
232 {
233 U32 coreId = OsGetCoreID();
234 enum GicIntState state;
235
236 if (intId < MIN_GIC_SPI_NUM) {
237 state = OsGicrGetIntState(coreId, intId);
238 OsGicrDisableInt(coreId, intId);
239 OsSicrSetIntGroup(coreId, intId, groupId);
240 if (state == GIC_ENABLE) {
241 OsGicrEnableInt(coreId, intId);
242 }
243 } else {
244 state = OsGicdGetIntState(intId);
245 OsGicdDisableInt(intId);
246 OsSicdSetIntGroup(intId, groupId);
247 if (state == GIC_ENABLE) {
248 OsGicdEnableInt(intId);
249 }
250 }
251 }
252
OsSicInitLocal(void)253 U32 OsSicInitLocal(void)
254 {
255 U32 ret;
256 U32 intId;
257
258 OsSicrInit();
259
260 ret = OsSiccInit();
261 if (ret != OS_OK) {
262 return ret;
263 }
264
265 for (intId = 0; intId < MIN_GIC_SPI_NUM; ++intId) {
266 OsSicSetGroup(intId, SIC_GROUP_G1NS);
267 }
268
269 return OS_OK;
270 }
271
OsSicdInit(void)272 void OsSicdInit(void)
273 {
274 union SicdCtrl sicdCtrl;
275
276 sicdCtrl.value = GIC_REG_READ(GICD_CTLR_S_ADDR);
277
278 if ((sicdCtrl.bits.enG0S == 1) || (sicdCtrl.bits.enG1Ns == 1) || (sicdCtrl.bits.enG1S == 1)) {
279 return;
280 }
281
282 sicdCtrl.bits.ds = 0;
283 sicdCtrl.bits.areNs = 1;
284 sicdCtrl.bits.areS = 1;
285 sicdCtrl.bits.enG1Ns = 1;
286 GIC_REG_WRITE(GICD_CTLR_S_ADDR, sicdCtrl.value);
287
288 OsGicdWaitCfgWork();
289 }
290
OsSicInitGlobal(void)291 void OsSicInitGlobal(void)
292 {
293 U32 intId;
294
295 OsSicdInit();
296
297 for (intId = MIN_GIC_SPI_NUM; intId < MAX_INT_NUM; ++intId) {
298 OsSicSetGroup(intId, SIC_GROUP_G1NS);
299 }
300 }
301 #elif (OS_GIC_VER == 2)
IsrRegister(U32 intNo,U32 pri)302 int IsrRegister(U32 intNo, U32 pri)
303 {
304 U32 bitn, reg, shift;
305 U32 *addr;
306
307 bitn = intNo / 32U;
308 addr = (U32 *)(GICD_ISENABLERn + 4U * bitn);
309 reg = *addr;
310 *addr = (reg | (0x1U << (intNo % 32U)));
311
312 bitn = intNo / 4U;
313 addr = (U32 *)(GICD_IPRIORITYn + 4U * bitn);
314 shift = (intNo % 4U) * 8U;
315 reg = (*addr) & ~(0xFFU << shift);
316 *addr = (reg | pri << shift);
317 }
318
OsGicInitCpuInterface(void)319 void OsGicInitCpuInterface(void)
320 {
321 int i;
322 U32 val;
323
324 GIC_REG_WRITE(0xFFFFFFFF, GICD_ICACTIVERn);
325 GIC_REG_WRITE(0xFFFF0000, GICD_ICENABLERn);
326 GIC_REG_WRITE(0x0000FFFF, GICD_ISENABLERn);
327
328 for (i = 0; i < 32; i += 4) {
329 GIC_REG_WRITE(0xA0A0A0A0, GICD_IPRIORITYn + i);
330 }
331
332 GIC_REG_WRITE(0xF0, GICC_PMR);
333 val = GIC_REG_READ(GICC_CTLR);
334 val &= ~GICC_CTLR_BYPASS_MASK;
335 val |= GICC_CTLR_ENABLE_MASK;
336 GIC_REG_WRITE(val, GICC_CTLR);
337 }
338 #endif
OsHwiInit(void)339 U32 OsHwiInit(void)
340 {
341 #if (OS_GIC_VER == 3)
342 U32 ret;
343
344 ret = OsSicInitLocal();
345 if (ret != OS_OK) {
346 return ret;
347 }
348
349 if(OsGetCoreID() == 0) {
350 OsSicInitGlobal();
351 }
352 #elif (OS_GIC_VER == 2)
353 OsGicInitCpuInterface();
354 #endif
355 return OS_OK;
356 }
357