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