• 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 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