/* * Copyright : (C) 2022 Phytium Information Technology, Inc. * All Rights Reserved. * * This program is OPEN SOURCE software: you can redistribute it and/or modify it * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd, * either version 1.0 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the Phytium Public License for more details. * * * FilePath: fgic.c * Date: 2022-03-28 09:30:23 * LastEditTime: 2022-03-28 09:30:24 * Description: This file is for the minimum required function implementations for this driver. * * Modify History: * Ver   Who        Date         Changes * ----- ------     --------    -------------------------------------- * 1.0 huanghe 2022/4/16 init commit */ #include "fgic.h" #include "fgic_distributor.h" #include "fgic_cpu_interface.h" #include "fgic_redistributor.h" #include "fgic_hw.h" #include "ftypes.h" #include "fkernel.h" #include "fassert.h" #include "fdebug.h" #define FGIC_DEBUG_TAG "FGIC" #define FGIC_ERROR(format, ...) FT_DEBUG_PRINT_E(FGIC_DEBUG_TAG, format, ##__VA_ARGS__) #define FGIC_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FGIC_DEBUG_TAG, format, ##__VA_ARGS__) #define FGIC_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FGIC_DEBUG_TAG, format, ##__VA_ARGS__) #define FGIC_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FGIC_DEBUG_TAG, format, ##__VA_ARGS__) #define FGIC_SPI_START_ID 32 #define FGIC_PPI_END_ID 31 #define FGIC_SGI_END_ID 15 #define FGIC_GICD_32_PER_REG 32 #define FGIC_GICD_16_PER_REG 16 #define FGIC_GICD_4_PER_REG 4 #define FGIC_INT_DEFAULT_PRI_X4 0xa0a0a0a0 /* 考虑到当前一般程序工作于EL1,对于NS 或 S 安全状态 ,0x80 - 0xff 的优先级都有存在的可能性 */ #define FGIC_CPU_INTERFACE_DEFAULT_FLITER 0xFF typedef enum { GICD_CTLR_RWP_WAIT = 0, /* Use GICD_CTLR for test */ GICR_CTLR_RWP_WAIT, /* Use GICR_CTLR for test */ } WAIT_RWP_MODE; /** * @name: FGicWaitRwp * @msg: Wait for register write pending * @param {uintptr} ctrl_base is a GICD_CTLR address * @param {WAIT_RWP_MODE} wait_mode * @return {*} */ static FError FGicWaitRwp(uintptr ctrl_base, WAIT_RWP_MODE wait_mode) { u32 rwp_mask; u32 timeout_cnt = 0; if (GICD_CTLR_RWP_WAIT == wait_mode) { rwp_mask = FGIC_GICD_CTLR_RWP_MASK; } else if (GICR_CTLR_RWP_WAIT == wait_mode) { rwp_mask = FGIC_GICR_CTLR_RWP_MASK; } else { FGIC_DEBUG_E(" wait_mode not in WAIT_RWP_MODE."); return FGIC_CTLR_ERR_TYPE; } while (FGIC_READREG32(ctrl_base, 0) & rwp_mask) { if (timeout_cnt ++ >= 0xffffff) { FGIC_DEBUG_E(" Wait rwp timeout."); return FGIC_CTLR_ERR_IN_GET; } } return FGIC_SUCCESS; } /** * @name: void FGicDistrubutiorInit(FGic *instance_p) * @msg: Initialize Distrubutior * @param {FGic} *instance_p is a pointer to the FGic instance. */ void FGicDistrubutiorInit(FGic *instance_p) { FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); u32 max_ints_mun, int_id, int_index; uintptr dis_base = instance_p->config.dis_base; max_ints_mun = instance_p->max_spi_num; /* Disable the distributor */ FGIC_WRITEREG32(dis_base, FGIC_GICD_CTLR_OFFSET, 0); FASSERT(FGicWaitRwp(dis_base + FGIC_GICD_CTLR_OFFSET, GICD_CTLR_RWP_WAIT) == FGIC_SUCCESS); if (instance_p->security == ONE_NS_SECURITY_STATE) { /* Make GICD_CTLR.DS = 1 ,Non-secure accesses are permitted to access and modify registers that control Group 0 interrupts */ FGIC_SETBIT(dis_base, FGIC_GICD_CTLR_OFFSET, FGIC_GICD_CTLR_DS_MASK); FASSERT(FGIC_READREG32(dis_base, FGIC_GICD_CTLR_OFFSET) & FGIC_GICD_CTLR_DS_MASK); } /* 关闭所有中断,并将中断分组默认为group 1 */ for (int_id = FGIC_SPI_START_ID; int_id < max_ints_mun; int_id += FGIC_GICD_32_PER_REG) { int_index = int_id / FGIC_GICD_32_PER_REG; /* Disables forwarding of the corresponding interrupt. */ FGIC_GICD_ICENABLER_WRITE_N_MASK(dis_base, int_id, FGIC_GICD_ICENABLER_DEFAULT_MASK); /* Changes the state of the corresponding interrupt from pending to inactive, or from active and pending to active. */ FGIC_GICD_ICPENDR_WRITE_N_MASK(dis_base, int_id, FGIC_GICD_ICPENDR_DEFAULT_MASK); if (instance_p->security == ONE_NS_SECURITY_STATE) { FGIC_GICD_IGROUPR_WRITE_N_MASK(dis_base, int_id, FGIC_GICD_ICPENDR_DEFAULT_MASK); } else { FGIC_GICD_IGROUPR_WRITE_N_MASK(dis_base, int_id, FGIC_GICD_ICPENDR_DEFAULT_MASK); } FGIC_GICD_IGRPMODR_WRITE_N_MASK(dis_base, int_id, FGIC_GICD_IGRPMODR_DEFAULT_MASK); } FASSERT(FGicWaitRwp(dis_base + FGIC_GICD_CTLR_OFFSET, GICD_CTLR_RWP_WAIT) == FGIC_SUCCESS); for (int_id = FGIC_SPI_START_ID; int_id < max_ints_mun; int_id += FGIC_GICD_4_PER_REG) { FGIC_GICD_IPRIORITYR_WRITE_N_MASK(dis_base, int_id, FGIC_INT_DEFAULT_PRI_X4); } for (int_id = FGIC_SPI_START_ID; int_id < max_ints_mun; int_id += FGIC_GICD_16_PER_REG) { FGIC_GICD_ICFGR_WRITE_N_MASK(dis_base, int_id, 0); /* level-sensitive */ } if (instance_p->security == ONE_NS_SECURITY_STATE) { FGIC_GICD_CTLR_WRITE(dis_base, GICD_CTLR_BIT_ARE_S | GICD_CTLR_ENABLE_GRP1_NS); } else { FGIC_GICD_CTLR_WRITE(dis_base, GICD_CTLR_BIT_ARE_NS | GICD_CTLR_ENABLE_GRP1_NS); } } /** * @name: FError FGicRedistrubutiorInit(FGic *instance_p) * @msg: Initialize Redistrubutior * @param {FGic} *instance_p is a pointer to the FGic instance. * @return {FError} FGIC_SUCCESS is success ,FGIC_ERR_IN_TIMEOUT is timeout */ FError FGicRedistrubutiorInit(FGic *instance_p) { FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); s32 int_id ; u32 timeout = 0; uintptr redis_base = instance_p->redis_base; uintptr sgi_base = instance_p->redis_base + FGIC_GICR_SGI_BASE_OFFSET; /* Clear processor sleep and wait till childasleep is cleard */ FGIC_GICR_WAKER_CLEAR_BIT(redis_base, FGIC_GICR_WAKER_PROCESSOR_SLEEP_MASK); while (FGIC_GICR_WAKER_READ(redis_base) & FGIC_GICR_WAKER_CHILDREN_ASLEEP_MASK) { timeout++; if (timeout >= 0xfffffff) { return FGIC_ERR_IN_TIMEOUT; } } FASSERT(FGicWaitRwp(redis_base, GICR_CTLR_RWP_WAIT) == FGIC_SUCCESS); FGIC_GICR_ICENABLER0_WRITE(sgi_base, FGIC_GICR_ICENABLER0_DEFAULT_MASK); /* Disable all sgi ppi */ /* Clear pending */ FGIC_GICR_ICPENDR0_WRITE(sgi_base, FGIC_GICR_ICPENDR0_DEFAULT_MASK); /* Set sgi ppi route to different security group */ if (instance_p->security == ONE_NS_SECURITY_STATE) { FGIC_GICR_IGROUPR0_WRITE(sgi_base, FGIC_GICR_IGROUPR0_DEFAULT_MASK); } else { FGIC_GICR_IGROUPR0_WRITE(sgi_base, FGIC_GICR_IGROUPR0_DEFAULT_MASK); } FGIC_GICR_IGRPMODR0_WRITE(sgi_base, FGIC_GICR_IGRPMODR0_DEFAULT_MASK); /* 默认所有优先级为0xa0 */ for (int_id = 0; int_id < FGIC_SPI_START_ID; int_id += FGIC_GICD_4_PER_REG) { FGIC_GICR_IPRIORITYR_WRITE(sgi_base, int_id, FGIC_INT_DEFAULT_PRI_X4); } FGIC_GICR_ICFGR0_WRITE(sgi_base, 0); /* set level-sensitive */ FGIC_GICR_ICFGR1_WRITE(sgi_base, 0); return FGIC_SUCCESS; } /** * @name: void FGicCpuInterfaceInit(void) * @msg: Initialize Cpu interface of current core */ void FGicCpuInterfaceInit(void) { u32 reg; reg = FGicGetICC_SRE_EL1(); if (!(reg & GICC_SRE_SRE)) { reg |= (GICC_SRE_SRE | GICC_SRE_DFB | GICC_SRE_DIB); FGicSetICC_SRE_EL1(reg); reg = FGicGetICC_SRE_EL1(); FASSERT(reg & GICC_SRE_SRE); } FGicSetICC_PMR(FGIC_CPU_INTERFACE_DEFAULT_FLITER); FGicEnableGroup1_EL1(); FGicSetICC_CTLR_EL1(GICC_CTLR_CBPR); /* ICC_BPR0_EL1 determines the preemption group for both Group 0 and Group 1 interrupts. */ } /** * @name: FError FGicCfgInitialize(FGic *instance_p, const FGicConfig *input_config_p , uintptr redis_base) * @msg: Initialize the GIC driver instance based on the incoming configuration * @param {FGic} *instance_p is a pointer to the FGic instance. * @param {FGicConfig} *input_config_p Configuration items that need to be applied in the instance * @param {uintptr} redis_base is the redistributor adress of current core * @return {*} */ FError FGicCfgInitialize(FGic *instance_p, const FGicConfig *input_config_p, uintptr redis_base) { u32 max_ints_mun; uintptr dis_base; FASSERT(instance_p && input_config_p); instance_p->config = *input_config_p; instance_p->redis_base = redis_base ; instance_p->is_ready = FT_COMPONENT_IS_READY; dis_base = instance_p->config.dis_base; max_ints_mun = FGIC_READREG32(dis_base, FGIC_GICD_TYPER_OFFSET); max_ints_mun &= FGIC_GICD_TYPER_ITLINESNUMBER_MASK ; max_ints_mun = ((max_ints_mun + 1) << 5) - 1; /* If the value of this field is N, the maximum SPI INTID is 32(N+1) minus 1. */ instance_p->max_spi_num = max_ints_mun; return FGIC_SUCCESS; } /** * @name: FError FGicIntEnable(FGic *instance_p,s32 int_id) * @msg: Enables the interrupt function based on the interrupt number * @param {FGic} *instance_p is a pointer to the FGic instance. * @param {s32} int_id is interrupt id * @return {*} */ FError FGicIntEnable(FGic *instance_p, s32 int_id) { FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); if (int_id > instance_p->max_spi_num) { FGIC_DEBUG_E("int_id is over max spi num for FGicIntEnable."); return FGIC_CTLR_ERR_NUM; } if (int_id <= FGIC_PPI_END_ID) { uintptr redis_base = instance_p->redis_base; FGicEnablePrivateInt(redis_base, int_id); } else { uintptr dis_base = instance_p->config.dis_base; FGicEnableSPI(dis_base, int_id); } return FGIC_SUCCESS ; } /** * @name: FError FGicIntEnable(FGic *instance_p,s32 int_id) * @msg: Disable the interrupt function based on the interrupt number * @param {FGic} *instance_p is a pointer to the FGic instance. * @param {s32} int_id is interrupt id */ FError FGicIntDisable(FGic *instance_p, s32 int_id) { FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); if (int_id > instance_p->max_spi_num) { FGIC_DEBUG_E("int_id is over max spi num for FGicIntDisable."); return FGIC_CTLR_ERR_NUM; } if (int_id <= FGIC_PPI_END_ID) { uintptr redis_base = instance_p->redis_base; FGicDisablePrivateInt(redis_base, int_id); } else { uintptr dis_base = instance_p->config.dis_base; FGicDisableSPI(dis_base, int_id); } return FGIC_SUCCESS ; } /** * @name: FError FGicSetPriority(FGic *instance_p,s32 int_id,u32 priority) * @msg: Sets the current interrupt priority value based on the interrupt number * @param {FGic} *instance_p is a pointer to the FGic instance. * @param {s32} int_id is interrupt id * @param {u32} priority is priority value ,valid bit is bit[0:7] * @return {*} */ FError FGicSetPriority(FGic *instance_p, s32 int_id, u32 priority) { FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); if (int_id > instance_p->max_spi_num) { FGIC_DEBUG_E("int_id is over max spi num for FGicSetPriority."); return FGIC_CTLR_ERR_IN_GET; } if (int_id <= FGIC_PPI_END_ID) { uintptr redis_base = instance_p->redis_base; FGicSetPrivatePriority(redis_base, int_id, priority); } else { uintptr dis_base = instance_p->config.dis_base; FGicSetSpiPriority(dis_base, int_id, priority); } return FGIC_SUCCESS ; } /** * @name: u32 FGicGetPriority(FGic *instance_p,s32 int_id) * @msg: Gets the current interrupt priority value based on the interrupt number * @param {FGic} *instance_p is a pointer to the FGic instance * @param {s32} int_id is interrupt id * @return {u32} priority value ,valid bit is bit[0:7] */ u32 FGicGetPriority(FGic *instance_p, s32 int_id) { u32 priority; FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); if (int_id > instance_p->max_spi_num) { FGIC_DEBUG_E("int_id is over max spi num for FGicGetPriority."); return (u32)FGIC_CTLR_ERR_IN_GET; } if (int_id <= FGIC_PPI_END_ID) { uintptr redis_base = instance_p->redis_base; priority = FGicGetPrivatePriority(redis_base, int_id); } else { uintptr dis_base = instance_p->config.dis_base; priority = FGicGetSpiPriority(dis_base, int_id); } return priority ; } /** * @name: FError FGicSetTriggerLevel(FGic *instance_p,s32 int_id,TRIGGER_LEVEL trigger_way) * @msg: Sets the interrupt triggering mode based on the current interrupt number * @param {FGic} *instance_p is a pointer to the FGic instance * @param {s32} int_id is interrupt id * @param {TRIGGER_LEVEL} trigger_way is trigger mode * @return {*} */ FError FGicSetTriggerLevel(FGic *instance_p, s32 int_id, TRIGGER_LEVEL trigger_way) { FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); if (int_id > instance_p->max_spi_num) { FGIC_DEBUG_E("int_id is over max spi num for FGicSetTriggerLevel."); return FGIC_CTLR_ERR_IN_SET; } if (int_id <= FGIC_SGI_END_ID) { uintptr redis_base = instance_p->redis_base; FGicSetSgiLevel(redis_base, int_id, trigger_way); } else if (int_id <= FGIC_PPI_END_ID) { uintptr redis_base = instance_p->redis_base; FGicSetPpiLevel(redis_base, int_id, trigger_way); } else { uintptr dis_base = instance_p->config.dis_base; FGicSetSpiLevel(dis_base, int_id, trigger_way); } return FGIC_SUCCESS ; } /** * @name: u32 FGicGetTriggerLevel(FGic *instance_p,s32 int_id) * @msg: Gets the interrupt triggering mode based on the current interrupt number * @param {FGic} *instance_p is a pointer to the FGic instance * @param {s32} int_id is interrupt id * @return {u32} triggering mode */ u32 FGicGetTriggerLevel(FGic *instance_p, s32 int_id) { u32 trigger_way; FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); if (int_id > instance_p->max_spi_num) { FGIC_DEBUG_E("int_id is over max spi num for FGicGetTriggerLevel."); return (u32)FGIC_CTLR_ERR_IN_GET; } if (int_id <= FGIC_SGI_END_ID) { uintptr redis_base = instance_p->redis_base; trigger_way = FGicGetSgiLevel(redis_base, int_id); } else if (int_id <= FGIC_PPI_END_ID) { uintptr redis_base = instance_p->redis_base; trigger_way = FGicGetPpiLevel(redis_base, int_id); } else { uintptr dis_base = instance_p->config.dis_base; trigger_way = FGicGetSpiLevel(dis_base, int_id); } return trigger_way ; } /** * @name: FGicSetSpiAffinityRouting * @msg: Set intermediate routing information for a specific SPI interrupt * @param {FGic} *instance_p is a pointer to the FGic instance. * @param {u32} int_id is interrupt vector for spi * @param {SPI_ROUTING_MODE} route_mode is the interrupt routing mode. * @param {u64} affinity is the affinity level ,format is * |--------[bit39-32]-------[bit23-16]-------------[bit15-8]--------[bit7-0] * |--------Affinity level3-----Affinity level2-----Affinity level1---Affinity level0 * @return {*} */ FError FGicSetSpiAffinityRouting(FGic *instance_p, s32 int_id, SPI_ROUTING_MODE route_mode, u64 affinity) { FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); uintptr dis_base = instance_p->config.dis_base; if ((int_id > instance_p->max_spi_num) || (int_id <= FGIC_PPI_END_ID)) { FGIC_DEBUG_E("int_id %d is out of range.", int_id); return FGIC_CTLR_ERR_IN_SET; } FGicSetSpiRoute(dis_base, int_id, route_mode, affinity); return FGIC_SUCCESS; } /** * @name: FGicGetAffinityRouting * @msg: Get intermediate routing information for a specific SPI interrupt * @param {FGic} *instance_p is a pointer to the FGic instance. * @param {u32} int_id is interrupt vector for spi * @param {SPI_ROUTING_MODE} *route_mode_p is a pointer to get interrupt routing mode. * @param {u64} *affinity_p is pointer to get affinity level ,format is * |--------[bit39-32]-------[bit23-16]-------------[bit15-8]--------[bit7-0] * |--------Affinity level3-----Affinity level2-----Affinity level1---Affinity level0 * @return {FError} */ FError FGicGetAffinityRouting(FGic *instance_p, s32 int_id, SPI_ROUTING_MODE *route_mode_p, u64 *affinity_p) { FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); FASSERT(route_mode_p != NULL); FASSERT(affinity_p != NULL); uintptr dis_base = instance_p->config.dis_base; u64 reg; if ((int_id > instance_p->max_spi_num) || (int_id <= FGIC_PPI_END_ID)) { FGIC_DEBUG_E("int_id %d is out of range.", int_id); return (u32)FGIC_CTLR_ERR_IN_GET; } reg = FGicGetSpiRoute(dis_base, int_id); *route_mode_p = reg & SPI_ROUTING_TO_ANY; *affinity_p = reg & FGIC_GICD_IROUTER_AFFINITY_MASK; return FGIC_SUCCESS; } /** * @name: FGicGenerateSgi * @msg: This interface is used for software generated interrupts * @param {FGic} *instance_p is a pointer to the FGic instance. * @param {u32} int_id is interrupt vector for spi * @param {u32} target_list is the set of PEs for which SGI interrupts will be generated. Each bit corresponds to the PE within a cluster with an Affinity 0 value equal to the bit number. * @param {SGI_ROUTING_MODE} routing_mode is Interrupt Routing Mode. * @param {u64} affinity is the affinity level ,format is * |--------[bit55-48]-------[bit39-32]-------------[bit23-16] * |--------Affinity level3-----Affinity level2-----Affinity level1 * @return {*} */ FError FGicGenerateSgi(FGic *instance_p, s32 int_id, u32 target_list, SGI_ROUTING_MODE routing_mode, u64 affinity) { FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); if (int_id > FGIC_SGI_END_ID) { FGIC_DEBUG_E("int_id %d is out of range.", int_id); return FGIC_CTLR_ERR_IN_SET; } FGicSetICC_SGI1R((int_id & FGIC_ICC_SGI1R_INTID_MASK) << 24, target_list, routing_mode, affinity); return FGIC_SUCCESS; } /** * @name: FGicDeactionInterrupt * @msg: Deactive Interruption of the current active state * @param {FGic} *instance_p is a pointer to the FGic instance. * @param {s32} int_id is interrupt id */ void FGicDeactionInterrupt(FGic *instance_p, s32 int_id) { FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); FGicSetICC_EOIR1(int_id); } /** * @name: FGicAcknowledgeInt * @msg: Acknowledge pending interrupt * @param {FGic} *instance_p is a pointer to the FGic instance. * @return {s32} interrupt id */ s32 FGicAcknowledgeInt(FGic *instance_p) { FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); return FGicGetICC_APR1(); } /** * @name: FGicSetPriorityFilter * @msg: By setting the parameter of ICC_PMR, the interrupt range that the interrupt controller can respond to is determined * @param {FGic} *instance_p is a pointer to the FGic instance. * @param {u32} priority_mask . If the priority of an interrupt is lower than the value indicated by this field, the interface signals the interrupt to the PE. * The reference values of priority_mask are as follows * |priority_mask---------------256-------254--------252------248-------240 * |Implemented priority bits---[7:0]----[7:1]------[7:2]-----[7:3]-----[7:4] * |priority the growing steps--any-----even value----4---------8--------16 */ void FGicSetPriorityFilter(FGic *instance_p, u32 priority_mask) { FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); FGicSetICC_PMR(priority_mask); } /** * @name: FGicGetPriorityFilter * @msg: Gets the current priority filtering value * @param {FGic} *instance_p is a pointer to the FGic instance. * @return {u32} Priority Mask for the CPU interface . If the priority of an interrupt is lower than the value * indicated by this field, the interface signals the interrupt to the PE. * The reference values of priority_mask are as follows * |return value----------------256-------254--------252------248-------240 * |Implemented priority bits---[7:0]----[7:1]------[7:2]-----[7:3]-----[7:4] * |priority the growing steps--any-----even value----4---------8--------16 */ u32 FGicGetPriorityFilter(FGic *instance_p) { FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); return FGicGetICC_PMR(); } /** * @name: FGicGetPriorityGroup * @msg: Get Binary point value * @param {FGic} *instance_p is a pointer to the FGic instance. * @return {u32} The relationship between Binary point value and grouping is as follows * |return value----------------0-------1--------2------3-------4------5------6-------7 * |Group priority field------[---]----[7:1]---[7:2]--[7:3]---[7:4]---[7:5]---[7:6]---[7] * |Subpriority field---------[---]-----[0]----[1:0]--[2:0]---[3:0]---[4:0]---[5:0]---[6:0] */ u32 FGicGetPriorityGroup(FGic *instance_p) { FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); return FGicGetICC_BPR1(); } /** * @name: FGicSetPriorityGroup * @msg: Sets the value of the current group priority * @param {FGic} *instance_p is a pointer to the FGic instance. * @param {u32} binary_point : The value of this field controls how the 8-bit interrupt priority field is split into a group priority field * The relationship between binary_point value and grouping is as follows * |binary_point----------------0-------1--------2------3-------4------5------6-------7 * |Group priority field------[---]----[7:1]---[7:2]--[7:3]---[7:4]---[7:5]---[7:6]---[7] * |Subpriority field---------[---]-----[0]----[1:0]--[2:0]---[3:0]---[4:0]---[5:0]---[6:0] */ void FGicSetPriorityGroup(FGic *instance_p, u32 binary_point) { FASSERT(instance_p); FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY); FGicSetICC_BPR1(binary_point); }