diff --git a/libcpu/arm/cortex-a/gic.c b/libcpu/arm/cortex-a/gic.c index 072ddc302bf..c1e050df40b 100644 --- a/libcpu/arm/cortex-a/gic.c +++ b/libcpu/arm/cortex-a/gic.c @@ -25,41 +25,60 @@ struct arm_gic rt_uint32_t cpu_hw_base; /* the base addrees of the gic cpu interface */ }; -/* 'ARM_GIC_MAX_NR' is the number of cores */ static struct arm_gic _gic_table[ARM_GIC_MAX_NR]; /** Macro to access the Generic Interrupt Controller Interface (GICC) */ -#define GIC_CPU_CTRL(hw_base) __REG32((hw_base) + 0x00U) -#define GIC_CPU_PRIMASK(hw_base) __REG32((hw_base) + 0x04U) -#define GIC_CPU_BINPOINT(hw_base) __REG32((hw_base) + 0x08U) -#define GIC_CPU_INTACK(hw_base) __REG32((hw_base) + 0x0cU) -#define GIC_CPU_EOI(hw_base) __REG32((hw_base) + 0x10U) -#define GIC_CPU_RUNNINGPRI(hw_base) __REG32((hw_base) + 0x14U) -#define GIC_CPU_HIGHPRI(hw_base) __REG32((hw_base) + 0x18U) -#define GIC_CPU_IIDR(hw_base) __REG32((hw_base) + 0xFCU) +#define GIC_CPU_CTRL(hw_base) __REG32((hw_base) + 0x00U) /* GICC_CTLR */ +#define GIC_CPU_PRIMASK(hw_base) __REG32((hw_base) + 0x04U) /* GICC_PMR */ +#define GIC_CPU_BINPOINT(hw_base) __REG32((hw_base) + 0x08U) /* GICC_BPR */ +#define GIC_CPU_INTACK(hw_base) __REG32((hw_base) + 0x0cU) /* GICC_IAR */ +#define GIC_CPU_EOI(hw_base) __REG32((hw_base) + 0x10U) /* GICC_EOIR */ +#define GIC_CPU_RUNNINGPRI(hw_base) __REG32((hw_base) + 0x14U) /* GICC_RPR */ +#define GIC_CPU_HIGHPRI(hw_base) __REG32((hw_base) + 0x18U) /* GICC_HPPIR */ +#define GIC_CPU_IIDR(hw_base) __REG32((hw_base) + 0xFCU) /* GICC_IIDR */ /** Macro to access the Generic Interrupt Controller Distributor (GICD) */ -#define GIC_DIST_CTRL(hw_base) __REG32((hw_base) + 0x000U) -#define GIC_DIST_TYPE(hw_base) __REG32((hw_base) + 0x004U) -#define GIC_DIST_IGROUP(hw_base, n) __REG32((hw_base) + 0x080U + ((n)/32U) * 4U) -#define GIC_DIST_ENABLE_SET(hw_base, n) __REG32((hw_base) + 0x100U + ((n)/32U) * 4U) -#define GIC_DIST_ENABLE_CLEAR(hw_base, n) __REG32((hw_base) + 0x180U + ((n)/32U) * 4U) -#define GIC_DIST_PENDING_SET(hw_base, n) __REG32((hw_base) + 0x200U + ((n)/32U) * 4U) -#define GIC_DIST_PENDING_CLEAR(hw_base, n) __REG32((hw_base) + 0x280U + ((n)/32U) * 4U) -#define GIC_DIST_ACTIVE_SET(hw_base, n) __REG32((hw_base) + 0x300U + ((n)/32U) * 4U) -#define GIC_DIST_ACTIVE_CLEAR(hw_base, n) __REG32((hw_base) + 0x380U + ((n)/32U) * 4U) -#define GIC_DIST_PRI(hw_base, n) __REG32((hw_base) + 0x400U + ((n)/4U) * 4U) -#define GIC_DIST_TARGET(hw_base, n) __REG32((hw_base) + 0x800U + ((n)/4U) * 4U) -#define GIC_DIST_CONFIG(hw_base, n) __REG32((hw_base) + 0xc00U + ((n)/16U) * 4U) -#define GIC_DIST_SOFTINT(hw_base) __REG32((hw_base) + 0xf00U) -#define GIC_DIST_CPENDSGI(hw_base, n) __REG32((hw_base) + 0xf10U + ((n)/4U) * 4U) -#define GIC_DIST_SPENDSGI(hw_base, n) __REG32((hw_base) + 0xf20U + ((n)/4U) * 4U) -#define GIC_DIST_ICPIDR2(hw_base) __REG32((hw_base) + 0xfe8U) +#define GIC_DIST_CTRL(hw_base) __REG32((hw_base) + 0x000U) /* GICD_CTLR */ +#define GIC_DIST_TYPE(hw_base) __REG32((hw_base) + 0x004U) /* GICD_TYPER */ +#define GIC_DIST_IGROUP(hw_base, n) __REG32((hw_base) + 0x080U + ((n)/32U) * 4U) /* GICD_IGROUPRn */ +#define GIC_DIST_ENABLE_SET(hw_base, n) __REG32((hw_base) + 0x100U + ((n)/32U) * 4U) /* GICD_ISENABLERn */ +#define GIC_DIST_ENABLE_CLEAR(hw_base, n) __REG32((hw_base) + 0x180U + ((n)/32U) * 4U) /* GICD_ICENABLERn */ +#define GIC_DIST_PENDING_SET(hw_base, n) __REG32((hw_base) + 0x200U + ((n)/32U) * 4U) /* GICD_ISPENDRn */ +#define GIC_DIST_PENDING_CLEAR(hw_base, n) __REG32((hw_base) + 0x280U + ((n)/32U) * 4U) /* GICD_ICPENDRn */ +#define GIC_DIST_ACTIVE_SET(hw_base, n) __REG32((hw_base) + 0x300U + ((n)/32U) * 4U) /* GICD_ISACTIVERn */ +#define GIC_DIST_ACTIVE_CLEAR(hw_base, n) __REG32((hw_base) + 0x380U + ((n)/32U) * 4U) /* GICD_ICACTIVERn */ +#define GIC_DIST_PRI(hw_base, n) __REG32((hw_base) + 0x400U + ((n)/4U) * 4U) /* GICD_IPRIORITYRn */ +#define GIC_DIST_TARGET(hw_base, n) __REG32((hw_base) + 0x800U + ((n)/4U) * 4U) /* GICD_ITARGETSRn */ +#define GIC_DIST_CONFIG(hw_base, n) __REG32((hw_base) + 0xc00U + ((n)/16U) * 4U) /* GICD_ICFGRn */ +#define GIC_DIST_SOFTINT(hw_base) __REG32((hw_base) + 0xf00U) /* GICD_SGIR */ +#define GIC_DIST_CPENDSGI(hw_base, n) __REG32((hw_base) + 0xf10U + ((n)/4U) * 4U) /* GICD_CPENDSGIRn */ +#define GIC_DIST_SPENDSGI(hw_base, n) __REG32((hw_base) + 0xf20U + ((n)/4U) * 4U) /* GICD_SPENDSGIRn */ +#define GIC_DIST_ICPIDR2(hw_base) __REG32((hw_base) + 0xfe8U) /* ICPIDR2 */ static unsigned int _gic_max_irq; +/** + * @brief Get the active interrupt number + * + * @note Read the GICC_IAR register and add the interrupt number offset to get + * the actual interrupt number. + * This read acts as an acknowledge for the interrupt, changing the interrupt + * state from pending to active. + * + * GICC_IAR register bit fields: + * - GICC_IAR[31:13]: Reserved, read as 0 + * - GICC_IAR[12:10]: CPUID + * For SGIs: This value is the CPUID that requested the interrupt. + * For other interrupts: This value reads as 0 (RAZ). + * - GICC_IAR[9:0]: Interrupt ID + * + * @param index GIC controller index + * + * @return The actual interrupt number (with offset added). + * Note: For SGIs, the return value may include CPUID information in the upper bits. + */ int arm_gic_get_active_irq(rt_uint32_t index) { int irq; @@ -71,6 +90,21 @@ int arm_gic_get_active_irq(rt_uint32_t index) return irq; } +/** + * @brief Acknowledge and end the interrupt + * + * @note This function completes the interrupt handling by: + * 1. Clearing the pending status of the interrupt in the Distributor (GICD_ICPENDRn). + * 2. Writing the interrupt ID to the End of Interrupt Register (GICC_EOIR). + * This signals the GIC that interrupt processing is complete and changes + * the interrupt state from active to inactive. + * + * This function should be called after the interrupt handler has finished + * processing the interrupt, typically at the end of the interrupt service routine. + * + * @param index GIC controller index + * @param irq The actual interrupt number (with offset) to acknowledge + */ void arm_gic_ack(rt_uint32_t index, int irq) { rt_uint32_t mask = 1U << (irq % 32U); @@ -84,6 +118,12 @@ void arm_gic_ack(rt_uint32_t index, int irq) GIC_CPU_EOI(_gic_table[index].cpu_hw_base) = irq; } +/** + * @brief Disable the forwarding of the corresponding interrupt + * + * @param index GIC controller index + * @param irq The actual interrupt number(with offset) + */ void arm_gic_mask(rt_uint32_t index, int irq) { rt_uint32_t mask = 1U << (irq % 32U); @@ -96,6 +136,12 @@ void arm_gic_mask(rt_uint32_t index, int irq) GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask; } +/** + * @brief Enables the forwarding of the corresponding interrupt + * + * @param index GIC controller index + * @param irq The actual interrupt number(with offset) + */ void arm_gic_umask(rt_uint32_t index, int irq) { rt_uint32_t mask = 1U << (irq % 32U); @@ -105,9 +151,17 @@ void arm_gic_umask(rt_uint32_t index, int irq) irq = irq - _gic_table[index].offset; RT_ASSERT(irq >= 0U); - GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask; + GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask; /* GICD_ISENABLERn */ } +/** + * @brief Identifies whether the interrupt is pending + * + * @param index GIC controller index + * @param irq The actual interrupt number(with offset) + * + * @return 0: not pending, 1: pending + */ rt_uint32_t arm_gic_get_pending_irq(rt_uint32_t index, int irq) { rt_uint32_t pend; @@ -119,12 +173,12 @@ rt_uint32_t arm_gic_get_pending_irq(rt_uint32_t index, int irq) if (irq >= 16U) { - pend = (GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL; + pend = (GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL; /* GICD_ISPENDRn */ } else { /* INTID 0-15 Software Generated Interrupt */ - pend = (GIC_DIST_SPENDSGI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL; + pend = (GIC_DIST_SPENDSGI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL; /* GICD_SPENDSGIRn */ /* No CPU identification offered */ if (pend != 0U) { @@ -139,6 +193,12 @@ rt_uint32_t arm_gic_get_pending_irq(rt_uint32_t index, int irq) return (pend); } +/** + * @brief Set the interrupt as pending + * + * @param index GIC controller index + * @param irq The actual interrupt number(with offset) + */ void arm_gic_set_pending_irq(rt_uint32_t index, int irq) { RT_ASSERT(index < ARM_GIC_MAX_NR); @@ -158,6 +218,12 @@ void arm_gic_set_pending_irq(rt_uint32_t index, int irq) } } +/** + * @brief clears the pending state of the interrupt + * + * @param index GIC controller index + * @param irq The actual interrupt number(with offset) + */ void arm_gic_clear_pending_irq(rt_uint32_t index, int irq) { rt_uint32_t mask; @@ -179,6 +245,24 @@ void arm_gic_clear_pending_irq(rt_uint32_t index, int irq) } } +/** + * @brief Configure whether the corresponding interrupt is edge-triggered or level-sensitive + * + * @note For SGIs (interrupt IDs 0-15), the Int_config fields are read-only, + * meaning that GICD_ICFGR0 is read-only. Writing to this register for SGIs + * will have no effect. + * + * For PPIs (interrupt IDs 16-31), it is IMPLEMENTATION DEFINED whether + * the most significant bit of the Int_config field is programmable. + * Some implementations may make PPI configuration registers read-only. + * + * This function is primarily intended for configuring SPIs (interrupt IDs 32+), + * which have fully programmable configuration registers. + * + * @param index GIC controller index + * @param irq The actual interrupt number (with offset) + * @param config 0: level-sensitive, 1: edge-triggered + */ void arm_gic_set_configuration(rt_uint32_t index, int irq, rt_uint32_t config) { rt_uint32_t icfgr; @@ -198,6 +282,14 @@ void arm_gic_set_configuration(rt_uint32_t index, int irq, rt_uint32_t config) GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq) = icfgr; } +/** + * @brief Identifies whether the corresponding interrupt is edge-triggered or level-sensitive + * + * @param index GIC controller index + * @param irq The actual interrupt number(with offset) + * + * @return 0: level-sensitive, 1: edge-triggered + */ rt_uint32_t arm_gic_get_configuration(rt_uint32_t index, int irq) { RT_ASSERT(index < ARM_GIC_MAX_NR); @@ -208,6 +300,12 @@ rt_uint32_t arm_gic_get_configuration(rt_uint32_t index, int irq) return (GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq) >> ((irq % 16U) >> 1U)); } +/** + * @brief Deactivates the corresponding interrupt + * + * @param index GIC controller index + * @param irq The actual interrupt number(with offset) + */ void arm_gic_clear_active(rt_uint32_t index, int irq) { rt_uint32_t mask = 1U << (irq % 32U); @@ -220,7 +318,14 @@ void arm_gic_clear_active(rt_uint32_t index, int irq) GIC_DIST_ACTIVE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask; } -/* Set up the cpu mask for the specific interrupt */ +/** + * @brief Set up the cpu mask for the specific interrupt + * + * @param index GIC controller index + * @param irq The actual interrupt number(with offset) + * + * @param cpumask CPU targets. Only the lower 8 bits are valid (bits [7:0]). + */ void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask) { rt_uint32_t old_tgt; @@ -238,6 +343,14 @@ void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask) GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) = old_tgt; } +/** + * @brief Get the CPU targets for the specific interrupt + * + * @param index GIC controller index + * @param irq The actual interrupt number(with offset) + * + * @return CPU targets + */ rt_uint32_t arm_gic_get_target_cpu(rt_uint32_t index, int irq) { RT_ASSERT(index < ARM_GIC_MAX_NR); @@ -248,6 +361,15 @@ rt_uint32_t arm_gic_get_target_cpu(rt_uint32_t index, int irq) return (GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL; } +/** + * @brief Set the priority for the specific interrupt + * + * @note The lower the value, the greater the priority of the corresponding interrupt. + * + * @param index GIC controller index + * @param irq The actual interrupt number (with offset) + * @param priority The priority to set.Only the lower 8 bits are valid (bits [7:0]). + */ void arm_gic_set_priority(rt_uint32_t index, int irq, rt_uint32_t priority) { rt_uint32_t mask; @@ -263,6 +385,15 @@ void arm_gic_set_priority(rt_uint32_t index, int irq, rt_uint32_t priority) GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq) = mask; } + +/** + * @brief Get the priority for the specific interrupt + * + * @param index GIC controller index + * @param irq The actual interrupt number(with offset) + * + * @return The priority of the corresponding interrupt.Only the lower 8 bits are valid (bits [7:0]). + */ rt_uint32_t arm_gic_get_priority(rt_uint32_t index, int irq) { RT_ASSERT(index < ARM_GIC_MAX_NR); @@ -273,6 +404,15 @@ rt_uint32_t arm_gic_get_priority(rt_uint32_t index, int irq) return (GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL; } +/** + * @brief Set the priority mask for the specific CPU + * + * @note Only interrupts with higher priority than the value in this + * register are signaled to the processor. + * + * @param index GIC controller index + * @param priority The priority mask to set.Only the lower 8 bits are valid (bits [7:0]). + */ void arm_gic_set_interface_prior_mask(rt_uint32_t index, rt_uint32_t priority) { RT_ASSERT(index < ARM_GIC_MAX_NR); @@ -281,6 +421,13 @@ void arm_gic_set_interface_prior_mask(rt_uint32_t index, rt_uint32_t priority) GIC_CPU_PRIMASK(_gic_table[index].cpu_hw_base) = priority & 0xFFUL; } +/** + * @brief Get the priority mask for the specific CPU + * + * @param index GIC controller index + * + * @return The priority mask to return. Only the lower 8 bits are valid (bits [7:0]). + */ rt_uint32_t arm_gic_get_interface_prior_mask(rt_uint32_t index) { RT_ASSERT(index < ARM_GIC_MAX_NR); @@ -288,16 +435,49 @@ rt_uint32_t arm_gic_get_interface_prior_mask(rt_uint32_t index) return GIC_CPU_PRIMASK(_gic_table[index].cpu_hw_base); } +/** + * @brief Set the binary point value for interrupt priority splitting + * + * @note This function sets the GICC_BPR (Binary Point Register) value, which is used + * to split the priority field into group priority and subpriority fields. + * The binary point determines how many bits are used for group priority: + * - A larger value results in fewer bits for group priority, + * reducing interrupt preemption capability. + * - A smaller value results in more bits for group priority, + * increasing interrupt preemption capability. + * - Only the lower 3 bits are valid (bits [2:0], range 0-7). + * + * @param index GIC controller index + * @param binary_point Binary point value. Only the lower 3 bits are valid (bits [2:0]). + */ void arm_gic_set_binary_point(rt_uint32_t index, rt_uint32_t binary_point) { GIC_CPU_BINPOINT(_gic_table[index].cpu_hw_base) = binary_point & 0x7U; } +/** + * @brief Get the binary point value for interrupt priority splitting + * + * @param index GIC controller index + * @return Binary point value. Only the lower 3 bits are valid (bits [2:0]). + */ rt_uint32_t arm_gic_get_binary_point(rt_uint32_t index) { return GIC_CPU_BINPOINT(_gic_table[index].cpu_hw_base); } +/** + * @brief Get the status of the specified interrupt + * + * @note This function reads both the active and pending status of the interrupt + * + * @param index GIC controller index + * @param irq The actual interrupt number (with offset) + * + * @return Encoded interrupt status: + * - Bit 0: Pending status + * - Bit 1: Active status + */ rt_uint32_t arm_gic_get_irq_status(rt_uint32_t index, int irq) { rt_uint32_t pending; @@ -314,6 +494,28 @@ rt_uint32_t arm_gic_get_irq_status(rt_uint32_t index, int irq) return ((active << 1U) | pending); } +/** + * @brief Send a Software Generated Interrupt (SGI) to specified CPU(s) + * + * @note This function writes to the GICD_SGIR (Software Generated Interrupt Register) + * to generate an SGI. The register value is constructed as follows: + * - Bits [25:24]: TargetListFilter - determines how the SGI is forwarded + * * 0b00: Forward to CPUs specified in CPUTargetList + * * 0b01: Forward to all CPUs except the requesting CPU + * * 0b10: Forward only to the requesting CPU + * * 0b11: Reserved + * - Bits [23:16]: CPUTargetList - 8-bit mask specifying target CPUs + * (only used when TargetListFilter = 0b00) + * * Each bit represents a CPU: bit 0 = CPU 0, bit 1 = CPU 1, etc. + * - Bits [3:0]: SGIINTID - the SGI interrupt ID (0-15) + * + * @param index GIC controller index + * @param irq The actual interrupt number (with offset). + * @param target_list CPU target mask. Only the lower 8 bits are valid (bits [7:0]). + * Each bit represents a CPU. Used when filter_list = 0b00. + * @param filter_list Target list filter mode. Only the lower 2 bits are valid (bits [1:0]). + * Determines how the SGI is forwarded to CPUs. + */ void arm_gic_send_sgi(rt_uint32_t index, int irq, rt_uint32_t target_list, rt_uint32_t filter_list) { RT_ASSERT(index < ARM_GIC_MAX_NR); @@ -324,6 +526,21 @@ void arm_gic_send_sgi(rt_uint32_t index, int irq, rt_uint32_t target_list, rt_ui GIC_DIST_SOFTINT(_gic_table[index].dist_hw_base) = ((filter_list & 0x3U) << 24U) | ((target_list & 0xFFUL) << 16U) | (irq & 0x0FUL); } +/** + * @brief Get the highest priority pending interrupt ID without acknowledging it + * + * @note This function reads the GICC_HPPIR (Highest Priority Pending Interrupt Register) + * to get the interrupt ID of the highest priority pending interrupt. + * + * Unlike reading GICC_IAR (via arm_gic_get_active_irq()), reading GICC_HPPIR + * does NOT acknowledge the interrupt. This means: + * - The interrupt state remains unchanged (still pending) + * + * @param index GIC controller index + * + * @return The 32-bit value read from the GICC_HPPIR register. + * The caller can extract specific fields (hardware interrupt ID without offset added). + */ rt_uint32_t arm_gic_get_high_pending_irq(rt_uint32_t index) { RT_ASSERT(index < ARM_GIC_MAX_NR); @@ -331,6 +548,14 @@ rt_uint32_t arm_gic_get_high_pending_irq(rt_uint32_t index) return GIC_CPU_HIGHPRI(_gic_table[index].cpu_hw_base); } +/** + * @brief Get the CPU Interface Identification Register (GICC_IIDR) value + * + * @param index GIC controller index + * + * @return The 32-bit value read from the GICC_IIDR register. + * The caller can extract specific fields (implementer, product ID, revision, architecture version.) + */ rt_uint32_t arm_gic_get_interface_id(rt_uint32_t index) { RT_ASSERT(index < ARM_GIC_MAX_NR); @@ -338,6 +563,19 @@ rt_uint32_t arm_gic_get_interface_id(rt_uint32_t index) return GIC_CPU_IIDR(_gic_table[index].cpu_hw_base); } +/** + * @brief Set the interrupt group for the specified interrupt + * + * @note This function configures the interrupt group in the GICD_IGROUPRn register. + * The interrupt group determines the security classification of the interrupt + * when the GIC implements Security Extensions: + * - Group 0 (group = 0): Secure interrupts, used for secure world + * - Group 1 (group = 1): Non-secure interrupts, used for non-secure world + * + * @param index GIC controller index + * @param irq The actual interrupt number (with offset) + * @param group Interrupt group: 0 for Group 0 (secure), 1 for Group 1 (non-secure) + */ void arm_gic_set_group(rt_uint32_t index, int irq, rt_uint32_t group) { rt_uint32_t igroupr; @@ -357,6 +595,19 @@ void arm_gic_set_group(rt_uint32_t index, int irq, rt_uint32_t group) GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq) = igroupr; } +/** + * @brief Get the interrupt group for the specified interrupt + * + * @note This function reads the interrupt group from the GICD_IGROUPRn register. + * The return value indicates which security group the interrupt belongs to: + * - 0: Group 0 (Secure interrupt) + * - 1: Group 1 (Non-secure interrupt) + * + * @param index GIC controller index + * @param irq The actual interrupt number (with offset) + * + * @return The interrupt group: 0 for Group 0 (secure), 1 for Group 1 (non-secure) + */ rt_uint32_t arm_gic_get_group(rt_uint32_t index, int irq) { RT_ASSERT(index < ARM_GIC_MAX_NR); @@ -367,6 +618,19 @@ rt_uint32_t arm_gic_get_group(rt_uint32_t index, int irq) return (GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL; } +/** + * @brief Initialize the GIC Distributor (GICD) + * + * @note: The exact bit definitions and behavior may vary depending on + * the GIC implementation (GICv1/GICv2) and security context. + * + * + * @param index GIC controller index + * @param dist_base Base address of the GIC Distributor (GICD) + * @param irq_start The first interrupt index offset in the vector table + * + * @return 0 + */ int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start) { unsigned int gic_type, i; @@ -427,6 +691,17 @@ int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start) return 0; } +/** + * @brief Initialize the GIC CPU Interface (GICC) + * + * @note: The exact bit definitions and behavior may vary depending on + * the GIC implementation (GICv1/GICv2) and security context. + * + * @param index GIC controller index + * @param cpu_base Base address of the GIC CPU Interface (GICC) + * + * @return 0 + */ int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base) { RT_ASSERT(index < ARM_GIC_MAX_NR); @@ -445,6 +720,11 @@ int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base) return 0; } +/** + * @brief Print the GIC information (version, base addr, max irq nums, security extension) + * + * @param index GIC controller index + */ void arm_gic_dump_type(rt_uint32_t index) { unsigned int gic_type; @@ -458,6 +738,11 @@ void arm_gic_dump_type(rt_uint32_t index) gic_type); } +/** + * @brief Print the GIC status (highest priority pending interrupt, enable status, pending status , active status) + * + * @param index + */ void arm_gic_dump(rt_uint32_t index) { unsigned int i, k;