• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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