10d163575Sopenharmony_ci/* 20d163575Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 30d163575Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. 40d163575Sopenharmony_ci * 50d163575Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 60d163575Sopenharmony_ci * are permitted provided that the following conditions are met: 70d163575Sopenharmony_ci * 80d163575Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of 90d163575Sopenharmony_ci * conditions and the following disclaimer. 100d163575Sopenharmony_ci * 110d163575Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list 120d163575Sopenharmony_ci * of conditions and the following disclaimer in the documentation and/or other materials 130d163575Sopenharmony_ci * provided with the distribution. 140d163575Sopenharmony_ci * 150d163575Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used 160d163575Sopenharmony_ci * to endorse or promote products derived from this software without specific prior written 170d163575Sopenharmony_ci * permission. 180d163575Sopenharmony_ci * 190d163575Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 200d163575Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 210d163575Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 220d163575Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 230d163575Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 240d163575Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 250d163575Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 260d163575Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 270d163575Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 280d163575Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 290d163575Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 300d163575Sopenharmony_ci */ 310d163575Sopenharmony_ci 320d163575Sopenharmony_ci#include "gic_common.h" 330d163575Sopenharmony_ci#include "gic_v3.h" 340d163575Sopenharmony_ci#include "los_typedef.h" 350d163575Sopenharmony_ci#include "los_hwi.h" 360d163575Sopenharmony_ci#include "los_hwi_pri.h" 370d163575Sopenharmony_ci#include "los_mp.h" 380d163575Sopenharmony_ci 390d163575Sopenharmony_ci#ifdef LOSCFG_ARCH_GIC_V3 400d163575Sopenharmony_ci 410d163575Sopenharmony_ciSTATIC UINT32 g_curIrqNum = 0; 420d163575Sopenharmony_ci 430d163575Sopenharmony_ciSTATIC INLINE UINT64 MpidrToAffinity(UINT64 mpidr) 440d163575Sopenharmony_ci{ 450d163575Sopenharmony_ci return ((MPIDR_AFF_LEVEL(mpidr, 3) << 32) | /* 3: Serial number, 32: Register bit offset */ 460d163575Sopenharmony_ci (MPIDR_AFF_LEVEL(mpidr, 2) << 16) | /* 2: Serial number, 16: Register bit offset */ 470d163575Sopenharmony_ci (MPIDR_AFF_LEVEL(mpidr, 1) << 8) | /* 1: Serial number, 8: Register bit offset */ 480d163575Sopenharmony_ci (MPIDR_AFF_LEVEL(mpidr, 0))); 490d163575Sopenharmony_ci} 500d163575Sopenharmony_ci 510d163575Sopenharmony_ci#ifdef LOSCFG_KERNEL_SMP 520d163575Sopenharmony_ci 530d163575Sopenharmony_ciSTATIC UINT32 NextCpu(UINT32 cpu, UINT32 cpuMask) 540d163575Sopenharmony_ci{ 550d163575Sopenharmony_ci UINT32 next = cpu + 1; 560d163575Sopenharmony_ci 570d163575Sopenharmony_ci while (next < LOSCFG_KERNEL_CORE_NUM) { 580d163575Sopenharmony_ci if (cpuMask & (1U << next)) { 590d163575Sopenharmony_ci goto OUT; 600d163575Sopenharmony_ci } 610d163575Sopenharmony_ci 620d163575Sopenharmony_ci next++; 630d163575Sopenharmony_ci } 640d163575Sopenharmony_ci 650d163575Sopenharmony_ciOUT: 660d163575Sopenharmony_ci return next; 670d163575Sopenharmony_ci} 680d163575Sopenharmony_ci 690d163575Sopenharmony_ciSTATIC UINT16 GicTargetList(UINT32 *base, UINT32 cpuMask, UINT64 cluster) 700d163575Sopenharmony_ci{ 710d163575Sopenharmony_ci UINT32 nextCpu; 720d163575Sopenharmony_ci UINT16 tList = 0; 730d163575Sopenharmony_ci UINT32 cpu = *base; 740d163575Sopenharmony_ci UINT64 mpidr = CPU_MAP_GET(cpu); 750d163575Sopenharmony_ci while (cpu < LOSCFG_KERNEL_CORE_NUM) { 760d163575Sopenharmony_ci tList |= 1U << (mpidr & 0xf); 770d163575Sopenharmony_ci 780d163575Sopenharmony_ci nextCpu = NextCpu(cpu, cpuMask); 790d163575Sopenharmony_ci if (nextCpu >= LOSCFG_KERNEL_CORE_NUM) { 800d163575Sopenharmony_ci goto out; 810d163575Sopenharmony_ci } 820d163575Sopenharmony_ci 830d163575Sopenharmony_ci cpu = nextCpu; 840d163575Sopenharmony_ci mpidr = CPU_MAP_GET(cpu); 850d163575Sopenharmony_ci if (cluster != (mpidr & ~0xffUL)) { 860d163575Sopenharmony_ci cpu--; 870d163575Sopenharmony_ci goto out; 880d163575Sopenharmony_ci } 890d163575Sopenharmony_ci } 900d163575Sopenharmony_ci 910d163575Sopenharmony_ciout: 920d163575Sopenharmony_ci *base = cpu; 930d163575Sopenharmony_ci return tList; 940d163575Sopenharmony_ci} 950d163575Sopenharmony_ci 960d163575Sopenharmony_ciSTATIC VOID GicSgi(UINT32 irq, UINT32 cpuMask) 970d163575Sopenharmony_ci{ 980d163575Sopenharmony_ci UINT16 tList; 990d163575Sopenharmony_ci UINT32 cpu = 0; 1000d163575Sopenharmony_ci UINT64 val, cluster; 1010d163575Sopenharmony_ci 1020d163575Sopenharmony_ci while (cpuMask && (cpu < LOSCFG_KERNEL_CORE_NUM)) { 1030d163575Sopenharmony_ci if (cpuMask & (1U << cpu)) { 1040d163575Sopenharmony_ci cluster = CPU_MAP_GET(cpu) & ~0xffUL; 1050d163575Sopenharmony_ci 1060d163575Sopenharmony_ci tList = GicTargetList(&cpu, cpuMask, cluster); 1070d163575Sopenharmony_ci 1080d163575Sopenharmony_ci /* Generates a Group 1 interrupt for the current security state */ 1090d163575Sopenharmony_ci val = ((MPIDR_AFF_LEVEL(cluster, 3) << 48) | /* 3: Serial number, 48: Register bit offset */ 1100d163575Sopenharmony_ci (MPIDR_AFF_LEVEL(cluster, 2) << 32) | /* 2: Serial number, 32: Register bit offset */ 1110d163575Sopenharmony_ci (MPIDR_AFF_LEVEL(cluster, 1) << 16) | /* 1: Serial number, 16: Register bit offset */ 1120d163575Sopenharmony_ci (irq << 24) | tList); /* 24: Register bit offset */ 1130d163575Sopenharmony_ci 1140d163575Sopenharmony_ci GiccSetSgi1r(val); 1150d163575Sopenharmony_ci } 1160d163575Sopenharmony_ci 1170d163575Sopenharmony_ci cpu++; 1180d163575Sopenharmony_ci } 1190d163575Sopenharmony_ci} 1200d163575Sopenharmony_ci 1210d163575Sopenharmony_ciVOID HalIrqSendIpi(UINT32 target, UINT32 ipi) 1220d163575Sopenharmony_ci{ 1230d163575Sopenharmony_ci GicSgi(ipi, target); 1240d163575Sopenharmony_ci} 1250d163575Sopenharmony_ci 1260d163575Sopenharmony_ciVOID HalIrqSetAffinity(UINT32 irq, UINT32 cpuMask) 1270d163575Sopenharmony_ci{ 1280d163575Sopenharmony_ci UINT64 affinity = MpidrToAffinity(NextCpu(0, cpuMask)); 1290d163575Sopenharmony_ci 1300d163575Sopenharmony_ci /* When ARE is on, use router */ 1310d163575Sopenharmony_ci GIC_REG_64(GICD_IROUTER(irq)) = affinity; 1320d163575Sopenharmony_ci} 1330d163575Sopenharmony_ci 1340d163575Sopenharmony_ci#endif 1350d163575Sopenharmony_ci 1360d163575Sopenharmony_ciSTATIC VOID GicWaitForRwp(UINT64 reg) 1370d163575Sopenharmony_ci{ 1380d163575Sopenharmony_ci INT32 count = 1000000; /* 1s */ 1390d163575Sopenharmony_ci 1400d163575Sopenharmony_ci while (GIC_REG_32(reg) & GICD_CTLR_RWP) { 1410d163575Sopenharmony_ci count -= 1; 1420d163575Sopenharmony_ci if (!count) { 1430d163575Sopenharmony_ci PRINTK("gic_v3: rwp timeout 0x%x\n", GIC_REG_32(reg)); 1440d163575Sopenharmony_ci return; 1450d163575Sopenharmony_ci } 1460d163575Sopenharmony_ci } 1470d163575Sopenharmony_ci} 1480d163575Sopenharmony_ci 1490d163575Sopenharmony_ciSTATIC INLINE VOID GicdSetGroup(UINT32 irq) 1500d163575Sopenharmony_ci{ 1510d163575Sopenharmony_ci /* configure spi as group 0 on secure mode and group 1 on unsecure mode */ 1520d163575Sopenharmony_ci#ifdef LOSCFG_ARCH_SECURE_MONITOR_MODE 1530d163575Sopenharmony_ci GIC_REG_32(GICD_IGROUPR(irq / 32)) = 0; /* 32: Interrupt bit width */ 1540d163575Sopenharmony_ci#else 1550d163575Sopenharmony_ci GIC_REG_32(GICD_IGROUPR(irq / 32)) = 0xffffffff; /* 32: Interrupt bit width */ 1560d163575Sopenharmony_ci#endif 1570d163575Sopenharmony_ci} 1580d163575Sopenharmony_ci 1590d163575Sopenharmony_ciSTATIC INLINE VOID GicrSetWaker(UINT32 cpu) 1600d163575Sopenharmony_ci{ 1610d163575Sopenharmony_ci GIC_REG_32(GICR_WAKER(cpu)) &= ~GICR_WAKER_PROCESSORSLEEP; 1620d163575Sopenharmony_ci DSB; 1630d163575Sopenharmony_ci ISB; 1640d163575Sopenharmony_ci while ((GIC_REG_32(GICR_WAKER(cpu)) & 0x4) == GICR_WAKER_CHILDRENASLEEP); 1650d163575Sopenharmony_ci} 1660d163575Sopenharmony_ci 1670d163575Sopenharmony_ciSTATIC INLINE VOID GicrSetGroup(UINT32 cpu) 1680d163575Sopenharmony_ci{ 1690d163575Sopenharmony_ci /* configure sgi/ppi as group 0 on secure mode and group 1 on unsecure mode */ 1700d163575Sopenharmony_ci#ifdef LOSCFG_ARCH_SECURE_MONITOR_MODE 1710d163575Sopenharmony_ci GIC_REG_32(GICR_IGROUPR0(cpu)) = 0; 1720d163575Sopenharmony_ci GIC_REG_32(GICR_IGRPMOD0(cpu)) = 0; 1730d163575Sopenharmony_ci#else 1740d163575Sopenharmony_ci GIC_REG_32(GICR_IGROUPR0(cpu)) = 0xffffffff; 1750d163575Sopenharmony_ci#endif 1760d163575Sopenharmony_ci} 1770d163575Sopenharmony_ci 1780d163575Sopenharmony_ciSTATIC VOID GicdSetPmr(UINT32 irq, UINT8 priority) 1790d163575Sopenharmony_ci{ 1800d163575Sopenharmony_ci UINT32 pos = irq >> 2; /* one irq have the 8-bit interrupt priority field */ 1810d163575Sopenharmony_ci UINT32 newPri = GIC_REG_32(GICD_IPRIORITYR(pos)); 1820d163575Sopenharmony_ci 1830d163575Sopenharmony_ci /* Shift and mask the correct bits for the priority */ 1840d163575Sopenharmony_ci newPri &= ~(GIC_PRIORITY_MASK << ((irq % 4) * GIC_PRIORITY_OFFSET)); 1850d163575Sopenharmony_ci newPri |= priority << ((irq % 4) * GIC_PRIORITY_OFFSET); 1860d163575Sopenharmony_ci 1870d163575Sopenharmony_ci GIC_REG_32(GICD_IPRIORITYR(pos)) = newPri; 1880d163575Sopenharmony_ci} 1890d163575Sopenharmony_ci 1900d163575Sopenharmony_ciSTATIC VOID GicrSetPmr(UINT32 irq, UINT8 priority) 1910d163575Sopenharmony_ci{ 1920d163575Sopenharmony_ci UINT32 cpu = ArchCurrCpuid(); 1930d163575Sopenharmony_ci UINT32 pos = irq >> 2; /* one irq have the 8-bit interrupt priority field */ 1940d163575Sopenharmony_ci UINT32 newPri = GIC_REG_32(GICR_IPRIORITYR0(cpu) + pos * 4); 1950d163575Sopenharmony_ci 1960d163575Sopenharmony_ci /* Clear priority offset bits and set new priority */ 1970d163575Sopenharmony_ci newPri &= ~(GIC_PRIORITY_MASK << ((irq % 4) * GIC_PRIORITY_OFFSET)); 1980d163575Sopenharmony_ci newPri |= priority << ((irq % 4) * GIC_PRIORITY_OFFSET); 1990d163575Sopenharmony_ci 2000d163575Sopenharmony_ci GIC_REG_32(GICR_IPRIORITYR0(cpu) + pos * 4) = newPri; 2010d163575Sopenharmony_ci} 2020d163575Sopenharmony_ci 2030d163575Sopenharmony_ciSTATIC VOID GiccInitPercpu(VOID) 2040d163575Sopenharmony_ci{ 2050d163575Sopenharmony_ci /* enable system register interface */ 2060d163575Sopenharmony_ci UINT32 sre = GiccGetSre(); 2070d163575Sopenharmony_ci if (!(sre & 0x1)) { 2080d163575Sopenharmony_ci GiccSetSre(sre | 0x1); 2090d163575Sopenharmony_ci 2100d163575Sopenharmony_ci /* 2110d163575Sopenharmony_ci * Need to check that the SRE bit has actually been set. If 2120d163575Sopenharmony_ci * not, it means that SRE is disabled at up EL level. We're going to 2130d163575Sopenharmony_ci * die painfully, and there is nothing we can do about it. 2140d163575Sopenharmony_ci */ 2150d163575Sopenharmony_ci sre = GiccGetSre(); 2160d163575Sopenharmony_ci LOS_ASSERT(sre & 0x1); 2170d163575Sopenharmony_ci } 2180d163575Sopenharmony_ci 2190d163575Sopenharmony_ci#ifdef LOSCFG_ARCH_SECURE_MONITOR_MODE 2200d163575Sopenharmony_ci /* Enable group 0 and disable grp1ns grp1s interrupts */ 2210d163575Sopenharmony_ci GiccSetIgrpen0(1); 2220d163575Sopenharmony_ci GiccSetIgrpen1(0); 2230d163575Sopenharmony_ci 2240d163575Sopenharmony_ci /* 2250d163575Sopenharmony_ci * For priority grouping. 2260d163575Sopenharmony_ci * The value of this field control show the 8-bit interrupt priority field 2270d163575Sopenharmony_ci * is split into a group priority field, that determines interrupt preemption, 2280d163575Sopenharmony_ci * and a subpriority field. 2290d163575Sopenharmony_ci */ 2300d163575Sopenharmony_ci GiccSetBpr0(MAX_BINARY_POINT_VALUE); 2310d163575Sopenharmony_ci#else 2320d163575Sopenharmony_ci /* enable group 1 interrupts */ 2330d163575Sopenharmony_ci GiccSetIgrpen1(1); 2340d163575Sopenharmony_ci#endif 2350d163575Sopenharmony_ci 2360d163575Sopenharmony_ci /* set priority threshold to max */ 2370d163575Sopenharmony_ci GiccSetPmr(0xff); 2380d163575Sopenharmony_ci 2390d163575Sopenharmony_ci /* EOI deactivates interrupt too (mode 0) */ 2400d163575Sopenharmony_ci GiccSetCtlr(0); 2410d163575Sopenharmony_ci} 2420d163575Sopenharmony_ci 2430d163575Sopenharmony_ciUINT32 HalCurIrqGet(VOID) 2440d163575Sopenharmony_ci{ 2450d163575Sopenharmony_ci return g_curIrqNum; 2460d163575Sopenharmony_ci} 2470d163575Sopenharmony_ci 2480d163575Sopenharmony_ciVOID HalIrqMask(UINT32 vector) 2490d163575Sopenharmony_ci{ 2500d163575Sopenharmony_ci INT32 i; 2510d163575Sopenharmony_ci const UINT32 mask = 1U << (vector % 32); /* 32: Interrupt bit width */ 2520d163575Sopenharmony_ci 2530d163575Sopenharmony_ci if ((vector > OS_USER_HWI_MAX) || (vector < OS_USER_HWI_MIN)) { 2540d163575Sopenharmony_ci return; 2550d163575Sopenharmony_ci } 2560d163575Sopenharmony_ci 2570d163575Sopenharmony_ci if (vector < 32) { /* 32: Interrupt bit width */ 2580d163575Sopenharmony_ci for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) { 2590d163575Sopenharmony_ci GIC_REG_32(GICR_ICENABLER0(i)) = mask; 2600d163575Sopenharmony_ci GicWaitForRwp(GICR_CTLR(i)); 2610d163575Sopenharmony_ci } 2620d163575Sopenharmony_ci } else { 2630d163575Sopenharmony_ci GIC_REG_32(GICD_ICENABLER(vector >> 5)) = mask; 2640d163575Sopenharmony_ci GicWaitForRwp(GICD_CTLR); 2650d163575Sopenharmony_ci } 2660d163575Sopenharmony_ci} 2670d163575Sopenharmony_ci 2680d163575Sopenharmony_ciVOID HalIrqUnmask(UINT32 vector) 2690d163575Sopenharmony_ci{ 2700d163575Sopenharmony_ci INT32 i; 2710d163575Sopenharmony_ci const UINT32 mask = 1U << (vector % 32); /* 32: Interrupt bit width */ 2720d163575Sopenharmony_ci 2730d163575Sopenharmony_ci if ((vector > OS_USER_HWI_MAX) || (vector < OS_USER_HWI_MIN)) { 2740d163575Sopenharmony_ci return; 2750d163575Sopenharmony_ci } 2760d163575Sopenharmony_ci 2770d163575Sopenharmony_ci if (vector < 32) { /* 32: Interrupt bit width */ 2780d163575Sopenharmony_ci for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) { 2790d163575Sopenharmony_ci GIC_REG_32(GICR_ISENABLER0(i)) = mask; 2800d163575Sopenharmony_ci GicWaitForRwp(GICR_CTLR(i)); 2810d163575Sopenharmony_ci } 2820d163575Sopenharmony_ci } else { 2830d163575Sopenharmony_ci GIC_REG_32(GICD_ISENABLER(vector >> 5)) = mask; /* 5: Register bit offset */ 2840d163575Sopenharmony_ci GicWaitForRwp(GICD_CTLR); 2850d163575Sopenharmony_ci } 2860d163575Sopenharmony_ci} 2870d163575Sopenharmony_ci 2880d163575Sopenharmony_ciVOID HalIrqPending(UINT32 vector) 2890d163575Sopenharmony_ci{ 2900d163575Sopenharmony_ci if ((vector > OS_USER_HWI_MAX) || (vector < OS_USER_HWI_MIN)) { 2910d163575Sopenharmony_ci return; 2920d163575Sopenharmony_ci } 2930d163575Sopenharmony_ci 2940d163575Sopenharmony_ci GIC_REG_32(GICD_ISPENDR(vector >> 5)) = 1U << (vector % 32); /* 5: Register bit offset, 32: Interrupt bit width */ 2950d163575Sopenharmony_ci} 2960d163575Sopenharmony_ci 2970d163575Sopenharmony_ciVOID HalIrqClear(UINT32 vector) 2980d163575Sopenharmony_ci{ 2990d163575Sopenharmony_ci GiccSetEoir(vector); 3000d163575Sopenharmony_ci ISB; 3010d163575Sopenharmony_ci} 3020d163575Sopenharmony_ci 3030d163575Sopenharmony_ciUINT32 HalIrqSetPrio(UINT32 vector, UINT8 priority) 3040d163575Sopenharmony_ci{ 3050d163575Sopenharmony_ci UINT8 prio = priority; 3060d163575Sopenharmony_ci 3070d163575Sopenharmony_ci if (vector > OS_HWI_MAX_NUM) { 3080d163575Sopenharmony_ci PRINT_ERR("Invalid irq value %u, max irq is %u\n", vector, OS_HWI_MAX_NUM); 3090d163575Sopenharmony_ci return LOS_NOK; 3100d163575Sopenharmony_ci } 3110d163575Sopenharmony_ci 3120d163575Sopenharmony_ci prio = prio & (UINT8)GIC_INTR_PRIO_MASK; 3130d163575Sopenharmony_ci 3140d163575Sopenharmony_ci if (vector >= GIC_MIN_SPI_NUM) { 3150d163575Sopenharmony_ci GicdSetPmr(vector, prio); 3160d163575Sopenharmony_ci } else { 3170d163575Sopenharmony_ci GicrSetPmr(vector, prio); 3180d163575Sopenharmony_ci } 3190d163575Sopenharmony_ci 3200d163575Sopenharmony_ci return LOS_OK; 3210d163575Sopenharmony_ci} 3220d163575Sopenharmony_ci 3230d163575Sopenharmony_ciVOID HalIrqInitPercpu(VOID) 3240d163575Sopenharmony_ci{ 3250d163575Sopenharmony_ci INT32 idx; 3260d163575Sopenharmony_ci UINT32 cpu = ArchCurrCpuid(); 3270d163575Sopenharmony_ci 3280d163575Sopenharmony_ci /* GICR init */ 3290d163575Sopenharmony_ci GicrSetWaker(cpu); 3300d163575Sopenharmony_ci GicrSetGroup(cpu); 3310d163575Sopenharmony_ci GicWaitForRwp(GICR_CTLR(cpu)); 3320d163575Sopenharmony_ci 3330d163575Sopenharmony_ci /* GICR: clear and mask sgi/ppi */ 3340d163575Sopenharmony_ci GIC_REG_32(GICR_ICENABLER0(cpu)) = 0xffffffff; 3350d163575Sopenharmony_ci GIC_REG_32(GICR_ICPENDR0(cpu)) = 0xffffffff; 3360d163575Sopenharmony_ci 3370d163575Sopenharmony_ci GIC_REG_32(GICR_ISENABLER0(cpu)) = 0xffffffff; 3380d163575Sopenharmony_ci 3390d163575Sopenharmony_ci for (idx = 0; idx < GIC_MIN_SPI_NUM; idx += 1) { 3400d163575Sopenharmony_ci GicrSetPmr(idx, MIN_INTERRUPT_PRIORITY); 3410d163575Sopenharmony_ci } 3420d163575Sopenharmony_ci 3430d163575Sopenharmony_ci GicWaitForRwp(GICR_CTLR(cpu)); 3440d163575Sopenharmony_ci 3450d163575Sopenharmony_ci /* GICC init */ 3460d163575Sopenharmony_ci GiccInitPercpu(); 3470d163575Sopenharmony_ci 3480d163575Sopenharmony_ci#ifdef LOSCFG_KERNEL_SMP 3490d163575Sopenharmony_ci /* unmask ipi interrupts */ 3500d163575Sopenharmony_ci HalIrqUnmask(LOS_MP_IPI_WAKEUP); 3510d163575Sopenharmony_ci HalIrqUnmask(LOS_MP_IPI_HALT); 3520d163575Sopenharmony_ci#endif 3530d163575Sopenharmony_ci} 3540d163575Sopenharmony_ci 3550d163575Sopenharmony_ciVOID HalIrqInit(VOID) 3560d163575Sopenharmony_ci{ 3570d163575Sopenharmony_ci UINT32 i; 3580d163575Sopenharmony_ci UINT64 affinity; 3590d163575Sopenharmony_ci 3600d163575Sopenharmony_ci /* disable distributor */ 3610d163575Sopenharmony_ci GIC_REG_32(GICD_CTLR) = 0; 3620d163575Sopenharmony_ci GicWaitForRwp(GICD_CTLR); 3630d163575Sopenharmony_ci ISB; 3640d163575Sopenharmony_ci 3650d163575Sopenharmony_ci /* set external interrupts to be level triggered, active low. */ 3660d163575Sopenharmony_ci for (i = 32; i < OS_HWI_MAX_NUM; i += 16) { /* 32: Start interrupt number, 16: Interrupt bit width */ 3670d163575Sopenharmony_ci GIC_REG_32(GICD_ICFGR(i / 16)) = 0; 3680d163575Sopenharmony_ci } 3690d163575Sopenharmony_ci 3700d163575Sopenharmony_ci /* config distributer, mask and clear all spis, set group x */ 3710d163575Sopenharmony_ci for (i = 32; i < OS_HWI_MAX_NUM; i += 32) { /* 32: Start interrupt number, 32: Interrupt bit width */ 3720d163575Sopenharmony_ci GIC_REG_32(GICD_ICENABLER(i / 32)) = 0xffffffff; /* 32: Interrupt bit width */ 3730d163575Sopenharmony_ci GIC_REG_32(GICD_ICPENDR(i / 32)) = 0xffffffff; /* 32: Interrupt bit width */ 3740d163575Sopenharmony_ci GIC_REG_32(GICD_IGRPMODR(i / 32)) = 0; /* 32: Interrupt bit width */ 3750d163575Sopenharmony_ci 3760d163575Sopenharmony_ci GicdSetGroup(i); 3770d163575Sopenharmony_ci } 3780d163575Sopenharmony_ci 3790d163575Sopenharmony_ci /* set spi priority as default */ 3800d163575Sopenharmony_ci for (i = 32; i < OS_HWI_MAX_NUM; i++) { /* 32: Start interrupt number */ 3810d163575Sopenharmony_ci GicdSetPmr(i, MIN_INTERRUPT_PRIORITY); 3820d163575Sopenharmony_ci } 3830d163575Sopenharmony_ci 3840d163575Sopenharmony_ci GicWaitForRwp(GICD_CTLR); 3850d163575Sopenharmony_ci 3860d163575Sopenharmony_ci /* disable all interrupts. */ 3870d163575Sopenharmony_ci for (i = 0; i < OS_HWI_MAX_NUM; i += 32) { /* 32: Interrupt bit width */ 3880d163575Sopenharmony_ci GIC_REG_32(GICD_ICENABLER(i / 32)) = 0xffffffff; /* 32: Interrupt bit width */ 3890d163575Sopenharmony_ci } 3900d163575Sopenharmony_ci 3910d163575Sopenharmony_ci /* enable distributor with ARE, group 1 enabled */ 3920d163575Sopenharmony_ci GIC_REG_32(GICD_CTLR) = CTLR_ENALBE_G0 | CTLR_ENABLE_G1NS | CTLR_ARE_S; 3930d163575Sopenharmony_ci 3940d163575Sopenharmony_ci /* set spi to boot cpu only. ARE must be enabled */ 3950d163575Sopenharmony_ci affinity = MpidrToAffinity(AARCH64_SYSREG_READ(mpidr_el1)); 3960d163575Sopenharmony_ci for (i = 32; i < OS_HWI_MAX_NUM; i++) { /* 32: Start interrupt number */ 3970d163575Sopenharmony_ci GIC_REG_64(GICD_IROUTER(i)) = affinity; 3980d163575Sopenharmony_ci } 3990d163575Sopenharmony_ci 4000d163575Sopenharmony_ci HalIrqInitPercpu(); 4010d163575Sopenharmony_ci 4020d163575Sopenharmony_ci#ifdef LOSCFG_KERNEL_SMP 4030d163575Sopenharmony_ci /* register inter-processor interrupt */ 4040d163575Sopenharmony_ci (VOID)LOS_HwiCreate(LOS_MP_IPI_WAKEUP, 0xa0, 0, OsMpWakeHandler, 0); 4050d163575Sopenharmony_ci (VOID)LOS_HwiCreate(LOS_MP_IPI_SCHEDULE, 0xa0, 0, OsMpScheduleHandler, 0); 4060d163575Sopenharmony_ci (VOID)LOS_HwiCreate(LOS_MP_IPI_HALT, 0xa0, 0, OsMpScheduleHandler, 0); 4070d163575Sopenharmony_ci#ifdef LOSCFG_KERNEL_SMP_CALL 4080d163575Sopenharmony_ci (VOID)LOS_HwiCreate(LOS_MP_IPI_FUNC_CALL, 0xa0, 0, OsMpFuncCallHandler, 0); 4090d163575Sopenharmony_ci#endif 4100d163575Sopenharmony_ci#endif 4110d163575Sopenharmony_ci} 4120d163575Sopenharmony_ci 4130d163575Sopenharmony_ciVOID HalIrqHandler(VOID) 4140d163575Sopenharmony_ci{ 4150d163575Sopenharmony_ci UINT32 iar = GiccGetIar(); 4160d163575Sopenharmony_ci UINT32 vector = iar & 0x3FFU; 4170d163575Sopenharmony_ci 4180d163575Sopenharmony_ci /* 4190d163575Sopenharmony_ci * invalid irq number, mainly the spurious interrupts 0x3ff, 4200d163575Sopenharmony_ci * valid irq ranges from 0~1019, we use OS_HWI_MAX_NUM to do 4210d163575Sopenharmony_ci * the checking. 4220d163575Sopenharmony_ci */ 4230d163575Sopenharmony_ci if (vector >= OS_HWI_MAX_NUM) { 4240d163575Sopenharmony_ci return; 4250d163575Sopenharmony_ci } 4260d163575Sopenharmony_ci g_curIrqNum = vector; 4270d163575Sopenharmony_ci 4280d163575Sopenharmony_ci OsInterrupt(vector); 4290d163575Sopenharmony_ci GiccSetEoir(vector); 4300d163575Sopenharmony_ci} 4310d163575Sopenharmony_ci 4320d163575Sopenharmony_ciCHAR *HalIrqVersion(VOID) 4330d163575Sopenharmony_ci{ 4340d163575Sopenharmony_ci UINT32 pidr = GIC_REG_32(GICD_PIDR2V3); 4350d163575Sopenharmony_ci CHAR *irqVerString = NULL; 4360d163575Sopenharmony_ci 4370d163575Sopenharmony_ci switch (pidr >> GIC_REV_OFFSET) { 4380d163575Sopenharmony_ci case GICV3: 4390d163575Sopenharmony_ci irqVerString = "GICv3"; 4400d163575Sopenharmony_ci break; 4410d163575Sopenharmony_ci case GICV4: 4420d163575Sopenharmony_ci irqVerString = "GICv4"; 4430d163575Sopenharmony_ci break; 4440d163575Sopenharmony_ci default: 4450d163575Sopenharmony_ci irqVerString = "unknown"; 4460d163575Sopenharmony_ci } 4470d163575Sopenharmony_ci return irqVerString; 4480d163575Sopenharmony_ci} 4490d163575Sopenharmony_ci 4500d163575Sopenharmony_ci#endif 451