• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "gic_common.h"
33 #include "los_hwi.h"
34 #include "los_hwi_pri.h"
35 #include "los_mp.h"
36 
37 STATIC_ASSERT(OS_USER_HWI_MAX <= 1020, "hwi max is too large!");
38 
39 #ifdef LOSCFG_ARCH_GIC_V2
40 
41 STATIC UINT32 g_curIrqNum = 0;
42 
43 #ifdef LOSCFG_KERNEL_SMP
44 /*
45  * filter description
46  *   0b00: forward to the cpu interfaces specified in cpu_mask
47  *   0b01: forward to all cpu interfaces
48  *   0b10: forward only to the cpu interface that request the irq
49  */
GicWriteSgi(UINT32 vector,UINT32 cpuMask,UINT32 filter)50 STATIC VOID GicWriteSgi(UINT32 vector, UINT32 cpuMask, UINT32 filter)
51 {
52     UINT32 val = ((filter & 0x3) << 24) | ((cpuMask & 0xFF) << 16) | /* 24, 16: Register bit offset */
53                  (vector & 0xF);
54 
55     GIC_REG_32(GICD_SGIR) = val;
56 }
57 
HalIrqSendIpi(UINT32 target,UINT32 ipi)58 VOID HalIrqSendIpi(UINT32 target, UINT32 ipi)
59 {
60     GicWriteSgi(ipi, target, 0);
61 }
62 
HalIrqSetAffinity(UINT32 vector,UINT32 cpuMask)63 VOID HalIrqSetAffinity(UINT32 vector, UINT32 cpuMask)
64 {
65     UINT32 offset = vector / 4; /* 4: Interrupt bit width */
66     UINT32 index = vector & 0x3;
67 
68     GIC_REG_8(GICD_ITARGETSR(offset) + index) = cpuMask;
69 }
70 #endif
71 
HalCurIrqGet(VOID)72 UINT32 HalCurIrqGet(VOID)
73 {
74     return g_curIrqNum;
75 }
76 
HalIrqMask(UINT32 vector)77 VOID HalIrqMask(UINT32 vector)
78 {
79     if ((vector > OS_USER_HWI_MAX) || (vector < OS_USER_HWI_MIN)) {
80         return;
81     }
82 
83     GIC_REG_32(GICD_ICENABLER(vector / 32)) = 1U << (vector % 32); /* 32: Interrupt bit width */
84 }
85 
HalIrqUnmask(UINT32 vector)86 VOID HalIrqUnmask(UINT32 vector)
87 {
88     if ((vector > OS_USER_HWI_MAX) || (vector < OS_USER_HWI_MIN)) {
89         return;
90     }
91 
92     GIC_REG_32(GICD_ISENABLER(vector >> 5)) = 1U << (vector % 32); /* 5, 32: Register bit offset */
93 }
94 
HalIrqPending(UINT32 vector)95 VOID HalIrqPending(UINT32 vector)
96 {
97     if ((vector > OS_USER_HWI_MAX) || (vector < OS_USER_HWI_MIN)) {
98         return;
99     }
100 
101     GIC_REG_32(GICD_ISPENDR(vector >> 5)) = 1U << (vector % 32); /* 5, 32: Register bit offset */
102 }
103 
HalIrqClear(UINT32 vector)104 VOID HalIrqClear(UINT32 vector)
105 {
106     GIC_REG_32(GICC_EOIR) = vector;
107 }
108 
HalIrqInitPercpu(VOID)109 VOID HalIrqInitPercpu(VOID)
110 {
111     /* unmask interrupts */
112     GIC_REG_32(GICC_PMR) = 0xFF;
113 
114     /* enable gic cpu interface */
115     GIC_REG_32(GICC_CTLR) = 1;
116 }
117 
HalIrqInit(VOID)118 VOID HalIrqInit(VOID)
119 {
120     UINT32 i;
121 
122     /* set external interrupts to be level triggered, active low. */
123     for (i = 32; i < OS_HWI_MAX_NUM; i += 16) { /* 32: Start interrupt number, 16: Interrupt bit width */
124         GIC_REG_32(GICD_ICFGR(i / 16)) = 0; /* 16: Register bit offset */
125     }
126 
127     /* set external interrupts to CPU 0 */
128     for (i = 32; i < OS_HWI_MAX_NUM; i += 4) { /* 32: Start interrupt number, 4: Interrupt bit width */
129         GIC_REG_32(GICD_ITARGETSR(i / 4)) = 0x01010101;
130     }
131 
132     /* set priority on all interrupts */
133     for (i = 0; i < OS_HWI_MAX_NUM; i += 4) { /* 4: Interrupt bit width */
134         GIC_REG_32(GICD_IPRIORITYR(i / 4)) = GICD_INT_DEF_PRI_X4;
135     }
136 
137     /* disable all interrupts. */
138     for (i = 0; i < OS_HWI_MAX_NUM; i += 32) { /* 32: Interrupt bit width */
139         GIC_REG_32(GICD_ICENABLER(i / 32)) = ~0; /* 32: Interrupt bit width */
140     }
141 
142     HalIrqInitPercpu();
143 
144     /* enable gic distributor control */
145     GIC_REG_32(GICD_CTLR) = 1;
146 
147 #ifdef LOSCFG_KERNEL_SMP
148     /* register inter-processor interrupt */
149     (VOID)LOS_HwiCreate(LOS_MP_IPI_WAKEUP, 0xa0, 0, OsMpWakeHandler, 0);
150     (VOID)LOS_HwiCreate(LOS_MP_IPI_SCHEDULE, 0xa0, 0, OsMpScheduleHandler, 0);
151     (VOID)LOS_HwiCreate(LOS_MP_IPI_HALT, 0xa0, 0, OsMpHaltHandler, 0);
152 #ifdef LOSCFG_KERNEL_SMP_CALL
153     (VOID)LOS_HwiCreate(LOS_MP_IPI_FUNC_CALL, 0xa0, 0, OsMpFuncCallHandler, 0);
154 #endif
155 #endif
156 }
157 
HalIrqHandler(VOID)158 VOID HalIrqHandler(VOID)
159 {
160     UINT32 iar = GIC_REG_32(GICC_IAR);
161     UINT32 vector = iar & 0x3FFU;
162 
163     /*
164      * invalid irq number, mainly the spurious interrupts 0x3ff,
165      * gicv2 valid irq ranges from 0~1019, we use OS_HWI_MAX_NUM
166      * to do the checking.
167      */
168     if (vector >= OS_HWI_MAX_NUM) {
169         return;
170     }
171     g_curIrqNum = vector;
172 
173     OsInterrupt(vector);
174 
175     /* use original iar to do the EOI */
176     GIC_REG_32(GICC_EOIR) = iar;
177 }
178 
HalIrqVersion(VOID)179 CHAR *HalIrqVersion(VOID)
180 {
181     UINT32 pidr = GIC_REG_32(GICD_PIDR2V2);
182     CHAR *irqVerString = NULL;
183 
184     switch (pidr >> GIC_REV_OFFSET) {
185         case GICV1:
186             irqVerString = "GICv1";
187             break;
188         case GICV2:
189             irqVerString = "GICv2";
190             break;
191         default:
192             irqVerString = "unknown";
193     }
194     return irqVerString;
195 }
196 
197 #endif
198