ATF:Gicv源码解读系列-gicv2_spis_configure_defaults

1、gicv2_spis_configure_defaults

用来配置SPI的一些默认的属性,SPI中断

  • SPI:(shared peripheral interrupt),共享外设中断,该中断来源于外设,但是该中断可以对所有的core有效。

在gic的文档里面有写这样一句话,来说明这个中断。

SPIs are routed from the source through the Distributor to the target Redistributor and the associated CPU 
interface

SPIs从源通过分发器路由到目标再分发器和相关的CPU接口,这里有个关键词目标。因此这个目标可以是一个或者多个。

/*******************************************************************************

  • Helper function to configure the default attributes of SPIs.
    ******************************************************************************/
    void gicv2_spis_configure_defaults(uintptr_t gicd_base)
    {
    unsigned int index, num_ints;

    num_ints = gicd_read_typer(gicd_base);

1-通过GICD_TYPER获得最多支持的SPI中断数量

	注:
	 gicd_read_typer(gicd_base);
	static inline unsigned int gicd_read_typer(uintptr_t base)
	{
		return mmio_read_32(base + GICD_TYPER);
	}

		GICD_TYPER寄存器:
		提供有关GIC实现支持的功能的信息。它表明:
		•GIC实施是否支持两种安全状态。
		•GIC实施支持的最大INTID数。
		•可用作中断目标的PE数量。


num_ints &= TYPER_IT_LINES_NO_MASK;
num_ints = (num_ints + 1U) << 5;

	注
	the maximum SPI INTID is 32(N+1)-1. For example, 00011 specifies that the maximum SPI 
	INTID is 127.
	从该字段派生的值指定GIC实现可能支持的最大SPI数。一个实现可能无法实现达到此最大值的所有SPI。

/*
 * Treat all SPIs as G1NS by default. The number of interrupts is
 * calculated as 32 * (IT_LINES + 1). We do 32 at a time.
 */
for (index = MIN_SPI_ID; index < num_ints; index += 32U)
	gicd_write_igroupr(gicd_base, index, ~0U);

2-通过IGROUPR设置中断的分组,对每次pe生效

		注
			*访问器,用于写入与中断“id”对应的GIC分发器IGROUPR,一次32个中断id。
						void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val)
				{
					unsigned int n = id >> IGROUPR_SHIFT;
					
					mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
				}
			GICD_IGROUPR 
			**控制相应的中断是在组0还是组1中。**
			对于SGI和PPI:
			•当中断的安全状态ARE为1时,该中断的字段为RES0,在这种情况下允许实现RAZ/WI字段。(RAZ/WI:read as zero, write ignored)
			•GICR_IGROUPR0提供了等效功能。
			当GICD_CTLR.DS==0时,寄存器为RAZ/WI,用于非安全访问。
			与未实现中断相对应的位是RAZ/WI。
			笔记
			当未为安全状态启用关联路由时,访问GICD_IGROUPR0访问与GICR_IGROUGR0相同的状态,并且必须更新与执行访问的PE关联的Redistributor状态。
			实现必须确保在写入时挂起的中断使用旧值或新值,并且必须确保中断不会丢失或处理多次。变化的影响必须在有限的时间内可见。
			配置
			这些寄存器在所有GIC配置中都可用。如果GIC实现支持两种安全状态,则这些寄存器是安全的。
			实现的GICD_IGROUPR<n>寄存器的数量为**GICD_TYPER.ITLinesNumber**+1。寄存器从0开始编号。
			GICD_IGROUPR0为每个连接的PE存储。此寄存器为中断0-31提供组状态位。
			属性
			GICD_IGROUPR<n>是一个32位寄存器。

在这里插入图片描述
在这里插入图片描述

		后面这段比较 重要,解释了为什么这句代码这么写的。
		如果为中断的安全状态启用了关联路由,则与中断对应的位与GICD_IGRPMODR<n>中的等效位连接,以形成定义中断组的2位字段。GICD_IGRPMODR<n>中描述了该字段的编码。
		如果针对中断的安全状态禁用了关联路由,则:
		•对应的GICD_IGRPMODR<n>位为RES0。
		•对于安全中断,中断为安全组0。
		•对于非安全中断,中断为非安全组1。
		对于INTID m,当DIV和MOD是整数除法和模运算时:
		•对应的GICD_IGROUP<n>编号n由n=m DIV 32给出。
		•所需GICD_IGROUP的偏移量为(0x080+(4*n))。
		•此寄存器中所需的组修饰符位的位数为m MOD 32。
		通常,所有GICD_IGROUPR<n>和GICD_IGRPMODR<n>寄存器的重置值均为0,**因此所有中断均为组0,除非通过对适当寄存器的安全访问将其重新编程为组1。**这里是手动把所有的都写成了1,每个中断对于每个pe,所以需要循环。应该是这个中断,对于所有的PE都是1。中断是循环量。

/* Setup the default SPI priorities doing four at a time */
for (index = MIN_SPI_ID; index < num_ints; index += 4U)
gicd_write_ipriorityr(gicd_base,
index,
GICD_IPRIORITYR_DEF_VAL)

3-通过GICD_IPRIORITYR设置了每个SPI中断的优先级

		注
		寄存器:GICD_IPRIORITYR
		保持相应中断的优先级,中断的优先级配置

/* Treat all SPIs as level triggered by default, 16 at a time */
for (index = MIN_SPI_ID; index < num_ints; index += 16U)
gicd_write_icfgr(gicd_base, index, 0U);
}

4-通过GICD_ICFGR确定相应的中断是边缘触发的还是电平触发的。

	注:
	寄存器 GICD_ICFGR
	确定相应的中断是边缘触发的还是电平触发的。

猜你喜欢

转载自blog.csdn.net/weixin_45264425/article/details/129433733