#include <arch.h>
#include <arch_helpers.h>
#include <platform_def.h>
#include <interrupt_mgmt.h>
#include <platform.h>
#include <bl_common.h>
#include <debug.h>
#include <mmio.h>
#include <runtime_svc.h>
#include <hwtf_plat_gic.h>
#include <hwtf_misc_lib.h>
#include <gicv3_private.h>
#include <tf_log.h>
uint32_t gic_interrupt_type_to_line(uint32_t cpuif_base, uint32_t type)
{
uint32_t gicc_ctlr_val = (uint32_t)mmio_read_32(cpuif_base + GICC_CTLR);
if ((type == INTR_TYPE_NS) || ((gicc_ctlr_val & FIQ_EN) == 0)) {
return __builtin_ctz(SCR_IRQ_BIT);
} else {
return __builtin_ctz(SCR_FIQ_BIT);
}
}
/*
gicr_waker_processorsleep 0->1:表示CPU准备进入休眠状态,请GIC准备休眠; */
void plat_ic_waker_down_cpu(unsigned long gicr_base, unsigned int coreid)
{
mmio_write_32((uintptr_t)gicr_base + GICR_WAKER + ((uintptr_t)coreid << 18), 0x2); // 18:bit移位 0x2 bit1从 0 -> 1
}
/* ******************************************************************************
* t00216239: Wait Gic Waker Down.
* **************************************************************************** */
void plat_ic_check_waker_down_cpu(unsigned long gicr_base, unsigned int coreid)
{
uint32_t time_count = 0;
while ((mmio_read_32((uintptr_t)gicr_base + GICR_WAKER +
((uintptr_t)coreid << 18)) & 0x4) != 0x4) { // 18:bit移位 0x4获取bit2的值
MicroSecondDelay(100); // 延时100us
time_count++;
if (time_count > 5000) { // 5000:这里最大等待500ms退出,保证充足的裕量,且不会触发饿狗
break;
}
}
}
/* BEGIN: Modefied by y00300051, 2016/05/18 问题单号:DTS2016051707015
* 产品约束正常情况函数不能有任何打印,错误打印只能向stderr打印,不能向stdout打印
*/
uint32_t gic_gicd_disable_spi(uint32_t gicd_base, uint32_t spi_id)
{
uint32_t iceanbler = 0;
uint32_t reg_index;
uint32_t bit_index;
if (!VERIFY_SPI_ID(spi_id)) {
aft_print(LOG_LEVEL_ERROR,
" The input Shared Peripheral Interrupts ID(%d) is out of range(%d - %d)!\r\n",
spi_id,
MIN_EXTERNEL_INT_ID,
MAX_EXTERNEL_INT_ID);
return (uint32_t)FAILED;
}
reg_index = (spi_id >> 5) - 1; // 5:bit移位
bit_index = spi_id & MAX_PPI_ID;
SETBIT(iceanbler, bit_index);
mmio_write_32(gicd_base + GICD_ICENABLER_SPI + (uint32_t)(reg_index << 2), iceanbler); // 2:bit移位
aft_print(LOG_LEVEL_INFO, "spi_id:%u, iceanbler:0x%x\n", spi_id, iceanbler);
isb();
dsb();
return OK;
}
uint32_t gic_gicd_get_spi_enable_status(uint32_t gicd_base, uint32_t spi_id, uint32_t *p_enable)
{
uint32_t iseanbler;
uint32_t reg_index;
uint32_t bit_index;
if (!VERIFY_SPI_ID(spi_id)) {
aft_print(LOG_LEVEL_ERROR,
" The input Shared Peripheral Interrupts ID(%d) is out of range(%d - %d)!\r\n",
spi_id,
MIN_EXTERNEL_INT_ID,
MAX_EXTERNEL_INT_ID);
return (uint32_t)FAILED;
}
reg_index = (spi_id >> 5) - 1; // 5:bit移位
bit_index = spi_id & MAX_PPI_ID;
// 这个寄存器是cpu banked ,所有cpu用同样的地址
iseanbler = (uint32_t)mmio_read_32(gicd_base + GICD_ISENALER_SPI + (uint32_t)(reg_index << 2)); // 2:bit移位
*p_enable = TSTBIT(iseanbler, bit_index);
return OK;
}
uint32_t gic_gicd_get_spi_active(uint32_t gicd_base, uint32_t spi_id, uint32_t *p_status)
{
uint32_t gicd_isactiver;
uint32_t reg_index;
uint32_t bit_index;
#if defined CPU_HI1383
if (!VERIFY_SPI_ID(spi_id)) {
aft_print(LOG_LEVEL_ERROR,
"The input Shared Peripheral Interrupts ID(%d) is out of range(%d - %d)!\r\n",
spi_id,
MIN_EXTERNEL_INT_ID,
MAX_EXTERNEL_INT_ID);
return (uint32_t)FAILED;
}
#endif
reg_index = (spi_id >> 5) - 1; // 5:bit移位
bit_index = spi_id & MAX_PPI_ID;
gicd_isactiver = (uint32_t)mmio_read_32(gicd_base + GICD_ISACTIVER_SPI + (uint32_t)(reg_index << 2)); // 2:bit移位
*p_status = TSTBIT(gicd_isactiver, bit_index);
return OK;
}
uint32_t gic_gicd_set_spi_igroup(uint32_t gicd_base, uint32_t spi_id, uint32_t group_id)
{
uint32_t reg_index;
uint32_t bit_index;
uint32_t igroupr;
uint32_t igrpmodr;
if (!VERIFY_SPI_ID(spi_id)) {
aft_print(LOG_LEVEL_ERROR,
"The input Shared Peripheral Interrupts ID(%d) is out of range(%d - %d)!\r\n",
spi_id,
MIN_EXTERNEL_INT_ID,
MAX_EXTERNEL_INT_ID);
return (uint32_t)FAILED;
}
if (group_id >= INT_GROUP_MAX) {
aft_print(LOG_LEVEL_ERROR, "The input Group ID(%d) is out of range(%d)!\r\n", group_id, INT_GROUP_MAX);
return (uint32_t)FAILED;
}
reg_index = (spi_id >> 5) - 1; // 5:bit移位
bit_index = spi_id & MAX_PPI_ID;
/* Configure the GICD_IGROUPR */
igroupr = (uint32_t)mmio_read_32(gicd_base + GICD_IGROUPR_SPI + (uint32_t)(reg_index << 2)); // 2:bit移位
if ((group_id == INT_GROUP_G0S) || (group_id == INT_GROUP_G1S)) {
CLRBIT(igroupr, bit_index);
} else {
SETBIT(igroupr, bit_index);
}
mmio_write_32(gicd_base + GICD_IGROUPR_SPI + (uint32_t)(reg_index << 2), igroupr); // 2:bit移位
aft_print(LOG_LEVEL_INFO,
" regaddr:0x%lx w:0x%x,r:0x%x\n",
(gicd_base + GICD_IGROUPR_SPI + (uint32_t)(reg_index << 2)),
igroupr, // 2:bit移位
mmio_read_32(gicd_base + GICD_IGROUPR_SPI + (uint32_t)(reg_index << 2))); // 2:bit移位
/* Configure the GICD_IGRPMOD */
igrpmodr = (uint32_t)mmio_read_32(gicd_base + GICD_IGRPMODR_SPI + (uint32_t)(reg_index << 2)); // 2:bit移位
if ((group_id == INT_GROUP_G0S) || (group_id == INT_GROUP_G1NS)) {
CLRBIT(igrpmodr, bit_index);
} else {
SETBIT(igrpmodr, bit_index);
}
mmio_write_32(gicd_base + GICD_IGRPMODR_SPI + (uint32_t)(reg_index << 2), igrpmodr); // 2:bit移位
aft_print(LOG_LEVEL_INFO,
" igrpmodaddr:0x%lx w:0x%x,r:0x%x\n",
(gicd_base + GICD_IGRPMODR_SPI + (uint32_t)(reg_index << 2)),
igrpmodr, // 2:bit移位
mmio_read_32(gicd_base + GICD_IGRPMODR_SPI + (uint32_t)(reg_index << 2))); // 2:bit移位
return OK;
}
/* ****************************************************************************
* 1. When ARE is zero, the safe state of the interrupt of this register is consistent with the definition of GICv2.
* 2. When ARE is used for interrupt security status, GICR_ICFGR0 and GICR_ICFGR1 provide
interrupts to RES0 and equivalent functions in GICD_ICFGR0 and GICD_ICFGR1.
* 3. SGI intterupt is the default edge trigger
GICD_ICFGR_SPI_NN 该寄存器每2bit表示一个N-N SPI中断是电平敏感还是边沿触发,i{0,1}
GICD_ICFGR_SPI第0~1bit相应的中断号为ID32,第2~3bit相应的中断号为ID33,逐次类推。
2bit是一个中断的配置域(int_cfg),其中的int_cfg[0]是保留的,
int_cfg[1]:0:相应的中断为电平敏感,1:相应的中断为边沿触发
**************************************************************************** */
uint32_t gic_gicd_set_spi_icfg(uint32_t gicd_base, uint32_t spi_id, uint32_t cft_type)
{
uint32_t gicd_icfg;
uint32_t reg_offset;
uint32_t bit_offset;
if (!VERIFY_SPI_ID(spi_id)) {
aft_print(LOG_LEVEL_ERROR,
" The input Shared Peripheral Interrupts ID(%d) is out of range(%d - %d)!\r\n",
spi_id,
MIN_EXTERNEL_INT_ID,
MAX_EXTERNEL_INT_ID);
return (uint32_t)FAILED;
}
if (cft_type > INT_EDGE_TIRGGERED) {
aft_print(LOG_LEVEL_ERROR,
" The input triggered-type (0x%x) is out of range(0x%x)!\n"
"\r\n",
cft_type,
INT_EDGE_TIRGGERED);
return (uint32_t)FAILED;
}
/* Program the GICD_ICFGR 寄存器地址是用对了,寄存器名写错了 */
// reg_offset代表的是第几个GICD_ICFGR_SPI,57号确实是1 故先减去0x20即前32个中断
// 4:根据代码逻辑来看是因为一个32bit的寄存器中只能存放16个spi中断的触发方式,所以要右移4bit
reg_offset = (spi_id - 0x20) >> 4; // 先减去0x20即前32个中断, 然后要右移4bit
bit_offset = (((spi_id & 0xF) << 1) + 1); // 0xF 取bit[3:0]的值 57号应该是19
gicd_icfg = (uint32_t)mmio_read_32(gicd_base + GICD_ICFGR_SPI_NN + (uint32_t)(reg_offset << 2)); // 2:bit移位
gicd_icfg &= ~((uint32_t)0x01 << bit_offset);
gicd_icfg |= (cft_type << bit_offset);
mmio_write_32(gicd_base + GICD_ICFGR_SPI_NN + (uint32_t)(reg_offset << 2), gicd_icfg); // 2:bit移位
aft_print(LOG_LEVEL_INFO,
"spiid:%d, regaddr:0x%lx, bit_offset:%d, write GICD_ICFGR_SPI:0x%x, read=0x%x\n",
spi_id,
(gicd_base + GICD_ICFGR_SPI_NN + (uint32_t)(reg_offset << 2)),
bit_offset,
gicd_icfg, // 2:bit移位
mmio_read_32(gicd_base + GICD_ICFGR_SPI_NN + (uint32_t)(reg_offset << 2))); // 2:bit移位
return OK;
}
/* ****************************************************************************
1. For SGI and PPI interrupts, the byte in this interrupted GICD_IPRIORITYR0 to GICD_IPRIORITYR7
is RES0, which provides equivalent functionality from the bytes in GICR_IPRIORITYR0 to GICR_IPRIORITYR7
GICD_IPRIORITYRn第0~7bit相应的中断号为ID4n,第8~15bit相应的中断号为ID4n+1,逐次类推。值越大优先级越低。
注:(1)此寄存器是按字节访问的;
(2)只能安全访问才能正确访问Group0中断优先级;
(3)安全中断对应的priority域的高5bit有效,非安全中断对应的priority域的高4bit有效。
**************************************************************************** */
uint32_t gic_gicd_set_spi_ipriority_s(uint32_t gicd_base, uint32_t spi_id, uint32_t prior)
{
uint32_t gicd_ipriority;
uint32_t reg_offset;
uint32_t bit_offset;
uint32_t active_status = 0;
uint32_t enable_status = 0;
if (!VERIFY_SPI_ID(spi_id)) {
aft_print(LOG_LEVEL_ERROR,
"SPI ID The input Shared Peripheral Interrupts ID(%d) is out of range(%d - %d)!\r\n",
spi_id,
MIN_EXTERNEL_INT_ID,
MAX_EXTERNEL_INT_ID);
return (uint32_t)FAILED;
}
if (prior > MAX_S_PRIORITY) {
aft_print(LOG_LEVEL_ERROR,
"The input priority(%d) is out of range(%d)!"
"\r\n",
prior,
MAX_S_PRIORITY);
return OK;
}
/* Ensure the interrupt is not active */
(void)gic_gicd_get_spi_active(gicd_base, spi_id, &active_status);
if (active_status != 0) {
aft_print(LOG_LEVEL_INFO, "get spi active Shared Peripheral Interrupts %d is active!\r\n", spi_id);
}
/* Ensure that the interrupt is disabled */
(void)gic_gicd_get_spi_enable_status(gicd_base, spi_id, &enable_status);
if (enable_status != 0) {
(void)gic_gicd_disable_spi(gicd_base, spi_id);
}
/* Program the priority */
// 减去0x20即前32个中断
// 根据代码逻辑来看是因为一个32bit的寄存器中只能存放四个中断的优先级,所以要右移2bit,reg_offset代表的是第几个GICD_IPRIORITYR
reg_offset = (spi_id - 0x20) >> 2; // 减去0x20即前32个中断, 然后右移2bit
// 一个中断占据8bit,所以要<<3,另外安全中断对应的priority域的高5bit有效,所以要加上3
bit_offset = ((spi_id & 0x3) << 3) + 0x3; // & 0x3是为了得知该spi中断在GICD_IPRIORITYR中的第几个中断
gicd_ipriority = (uint32_t)mmio_read_32(gicd_base + GICD_IPRIORITYR_SPI_S + (uint32_t)(reg_offset << 2)); // 2:bit移位
gicd_ipriority &= ~((uint32_t)0x1F << bit_offset); // 将0x1F 位移上述算出的bitoffset
gicd_ipriority |= (prior << bit_offset);
mmio_write_32(gicd_base + GICD_IPRIORITYR_SPI_S + (uint32_t)(reg_offset << 2), gicd_ipriority); // 2:bit移位
aft_print(LOG_LEVEL_INFO,
"gicd ipriority:regaddr:0x%lx write spi_id:%u,w:0x%x,r:0x%x\n",
(gicd_base + GICD_IPRIORITYR_SPI_S + (uint32_t)(reg_offset << 2)),
spi_id,
gicd_ipriority, // 2:bit移位
mmio_read_32(gicd_base + GICD_IPRIORITYR_SPI_S + (uint32_t)(reg_offset << 2))); // 2:bit移位
return OK;
}
/*
GICD_ITARGETSR_SPI SPI_BLOCK每32bit对应一个中断的所有相应的CPU Interface。h{0,223} 0x0880+h*4
该寄存器为NNSPI中断分发目的CPU配置寄存器,每个中断使用一个寄存器配置,支持32个NNSPI配置。
GICD_ITARGETSRn采用位掩码的方式,设置为1说明发送到相应的核,每个中断号支持设置32个目标核。
注:只能安全访问才能正确访问Group0中断;
0x0880~0x08FC的偏移地址为NNSPI路由配置地址;
0x0900~0x0C00的偏移地址无效;
*/
uint32_t gic_gicd_itarget_spi2allcore(uint32_t gicd_base, uint32_t spi_id)
{
uint32_t itarget = 0xff; /* target to all cpu */
mmio_write_32((uintptr_t)(gicd_base + GICD_ITARGETSR_LOW + (uintptr_t)spi_id * 4), // 4
itarget); // 从GICD_ITARGETSR_LOW开始,不用对spiid减31了
aft_print(LOG_LEVEL_INFO,
"gicd base spi_id:%u addr:0x%lx, val:0x%x\n",
spi_id,
gicd_base + GICD_ITARGETSR_LOW + spi_id * 4, // 4
mmio_read_32(gicd_base + GICD_ITARGETSR_LOW + (uintptr_t)spi_id * 4)); // 4
return OK;
}
/* ****************************************************************************
Bits corresponding to group 0 and group 1 security interrupts can only be enabled via secure access
GICD_ISENABLER_SPI
spi单个中断的使能寄存器,决定是否发给Cpu Interface。
m的值由GICD_TYPER.ITLinesNumber决定,m{0,2} tab
0x0104+m*4
32 RW 0x00000000
gicd_spi_setenable 31:0 RW 0x00000000
"GICD_ISENABLERn第abit相应的中断号为ID(32*n+a),第a+1bit相应的中断号为ID(32*n+a+1),逐次类推。
对于读:0:相应的中断不使能; 1:相应的中断使能
对于写:0:忽略,不起作用; 1:使能相应的中断
注:(1)只能安全访问才能访问Group0中断对应的bit;" 中断丢失 Y
**************************************************************************** */
uint32_t gic_gicd_enable_spi(uint32_t gicd_base, uint32_t spi_id)
{
uint32_t iseanbler = 0;
uint32_t reg_index;
uint32_t bit_index;
if (!VERIFY_SPI_ID(spi_id)) {
aft_print(LOG_LEVEL_ERROR,
"The input Shared Peripheral Interrupts ID(%d) is out of range(%d - %d)!\r\n",
spi_id,
MIN_EXTERNEL_INT_ID,
MAX_EXTERNEL_INT_ID);
return (uint32_t)FAILED;
}
reg_index = (spi_id >> 5) - 1; // 57号中断是0
bit_index = spi_id & MAX_PPI_ID;
SETBIT(iseanbler, bit_index);
mmio_write_32(gicd_base + GICD_ISENALER_SPI + (uint32_t)(reg_index << 2), iseanbler); // 2:bit移位
aft_print(LOG_LEVEL_INFO,
" spi_id:%d reg_addr:0x%lx,bit_index:%d, w :0x%x, r:0x%x\n",
spi_id,
(gicd_base + GICD_ISENALER_SPI + (uint32_t)(reg_index << 2)),
bit_index,
iseanbler, // 2:bit移位
mmio_read_32(gicd_base + GICD_ISENALER_SPI + (uint32_t)(reg_index << 2))); // 2:bit移位
return OK;
}
uint32_t gic_gicd_enable_g0s(uint32_t gicd_base)
{
uint32_t gicd_ctlr_s;
gicd_ctlr_s = (uint32_t)mmio_read_32(gicd_base + GICD_CTLR_S);
gicd_ctlr_s |= gicd_ctlr_enablegrp0;
mmio_write_32(gicd_base + GICD_CTLR_S, gicd_ctlr_s);
aft_print(LOG_LEVEL_INFO, "gicd_ctlr_s:0x%x\n", mmio_read_32(gicd_base + GICD_CTLR_S));
isb();
dsb();
return OK;
}
uint32_t gic_set_mask_priority(uint32_t mask_prior)
{
uint32_t gicc_pmr;
if (mask_prior > GIC_MAX_MASK_PRIOR) {
/* Out of range mask priority */
aft_print(LOG_LEVEL_NOTICE, " mask_prior:[%u] is out of rang.\n", mask_prior);
return (uint32_t)FAILED;
}
/* set priority of int */
// 配置GICC_PMR设置中断屏蔽优先级
gicc_pmr = (uint32_t)read_icc_pmr_el1();
gicc_pmr |= (mask_prior & 0xf8); // 0xf8:中断优先级配置值,配置bit[7]~bit[3]
write_icc_pmr_el1(gicc_pmr);
WARN(" write gicc_pmr:0x%x\n", gicc_pmr);
return OK;
}
uint32_t gic_gicr_clr_waker(uint32_t gicr_base)
{
uint32_t gicr_waker;
uint32_t i = 0;
gicr_waker = mmio_read_32(gicr_base + GICR_WAKER + (((uintptr_t)(plat_my_core_pos())) << 18)); // 18:bit移位
gicr_waker &= (uint32_t)~WAKER_PS;
gicr_write_waker(gicr_base + (((uintptr_t)(plat_my_core_pos())) << 18), gicr_waker); // 18:bit移位
/* Need to clear to fall of childrenasleep. */
isb();
dsb();
gicr_waker = (uint32_t)gicr_read_waker(gicr_base + (((uintptr_t)(plat_my_core_pos())) << 18)); // 18:bit移位
while ((gicr_waker & WAKER_CA) != 0) {
if (i % 400 == 0) { // 每400ms喂狗一次
do_clear_watchdog();
}
do_clear_watchdog();
delay_ns(1000000); // delay 1000000 ns
gicr_waker = (uint32_t)gicr_read_waker(gicr_base + (((uintptr_t)(plat_my_core_pos())) << 18)); // 18:bit移位
i++;
if (i > 10000) { // 超过10000*1000000ns
aft_print(LOG_LEVEL_INFO, "reset_core gicr not waker!\n");
break;
}
}
return OK;
}
uint32_t gicv3_interrupt_type_to_line(uint32_t type)
{
if (type != INTR_TYPE_NS && type != INTR_TYPE_EL3 && type != INTR_TYPE_S_EL1) {
return (uint32_t)FAILED;
}
return __builtin_ctz(SCR_FIQ_BIT);
}
/* ****************************************************************************
Set a Shared Peripheral Interrupts route to the processor specified by a.b.c.d
[NOTE]: 1. These registers provide the routing information when ARE
is set for the security state of the associated interrupts.
When ARE is not set, these registers are RES0.
2. In systems supporting two security states, the GICD_IROUTERn
registers associated with secure interrupts may only be accessed
by secure accesses and are RAZ/WI for non-secure accesses
3. when ARE becomes one for a security state the value of all
writeable fields in this register is UNKNOWN for that security state.
GICD_IROUTERN_L 亲和性路由寄存器
GICD_IROUTERn_l每个寄存器对应一个中断ID,寄存器n对应IDn。
0:按亲和性路由配置的a.b.c.d CPU进行路由;
1:路由给整个系统所有CPU中的一个。
注
(1)中断ID0~31对应SGI和PPI中断,SGI的路由方式由SGIR或generateSGI命令获取,
PPI中断只发给本处理器,均不适用route寄存器。所以本寄存器对0~31中断保留。
(2)只能安全访问才能访问Group0中断对应的bit;
gicd_affinity2 23:16 RW 0x00
"亲和性分层中,A2的值。
bit[6:5]指示Socket ID,范围0~3;
bit[4:3]指示Socket内SCLID,范围0~3。
bit[2:0]指示SCL内CLUID,范围0~7。其他bit无效为RO/WI;"
gicd_affinity1 15:8 RW 0x00
"bit[1:0]指示CLUSTER内CPUID,范围0~3。其他bit无效为RO/WI;"
gicd_affinity0 7:0 RO 0x00
Affinity level 0. The level identifies individual threads within a multi-threaded core.
The taishan core is single-threaded, so this field has the value 0x00.
**************************************************************************** */
uint32_t gic_gicd_route_spi2cpu(uint32_t gicd_base, uint32_t spi_id, uint32_t aff2, uint32_t aff1, uint32_t aff0)
{
uint32_t gicd_irouter;
uint32_t active_status = 0;
uint32_t enable_status = 0;
uint32_t Die_id = 0x18;
/* Ensure the interrupt is not active */
(void)gic_gicd_get_spi_active(gicd_base, spi_id, &active_status);
if (active_status != 0) {
aft_print(LOG_LEVEL_INFO, "get spi active SPI_id:%d is active!\r\n", spi_id);
}
/* Ensure that the interrupt is disabled */
(void)gic_gicd_get_spi_enable_status(gicd_base, spi_id, &enable_status);
if (enable_status != 0) {
(void)gic_gicd_disable_spi(gicd_base, spi_id);
}
gicd_irouter = aff0 | (aff1 << 8) | ((Die_id | aff2) << 16); // 8,16:bit移位
mmio_write_32(gicd_base + GICD_IROUTERN_L + (spi_id << 3), gicd_irouter); // 3:bit移位
aft_print(LOG_LEVEL_INFO,
"get spi active regaddr:0x%lx,w:0x%x, r:0x%x\n",
gicd_base + GICD_IROUTERN_L + (spi_id << 3),
gicd_irouter, // 3:bit移位
mmio_read_32(gicd_base + GICD_IROUTERN_L + (spi_id << 3))); // 3:bit移位
return OK;
}
/* BEGIN: Modefied by y00300051, 2016/3/12 问题单号:DTS2016031202055 */
uint32_t gic_gicd_disable_g0s(uint32_t gicd_base)
{
uint32_t gicd_ctlr_s;
gicd_ctlr_s = (uint32_t)mmio_read_32(gicd_base + GICD_CTLR_S);
gicd_ctlr_s &= (~gicd_ctlr_enablegrp0);
mmio_write_32(gicd_base + GICD_CTLR_S, gicd_ctlr_s);
aft_print(LOG_LEVEL_INFO, "write gicd_ctlr_sa:0x%x\n", gicd_ctlr_s);
isb();
dsb();
return OK;
}
uint32_t gic_gicd_disable_g1s(uint32_t gicd_base)
{
uint32_t gicd_ctlr_s;
gicd_ctlr_s = (uint32_t)mmio_read_32(gicd_base + GICD_CTLR_S);
gicd_ctlr_s &= (~gicd_ctlr_enablesgrp1);
mmio_write_32(gicd_base + GICD_CTLR_S, gicd_ctlr_s);
aft_print(LOG_LEVEL_INFO, "gicd_ctlr_ss:0x%x\n", gicd_ctlr_s);
isb();
dsb();
return OK;
}
uint32_t gic_gicd_disable_g1ns(uint32_t gicd_base)
{
uint32_t gicd_ctlr_s;
gicd_ctlr_s = (uint32_t)mmio_read_32(gicd_base + GICD_CTLR_NS);
gicd_ctlr_s &= (~gicd_ctlr_enablensgrp1);
mmio_write_32(gicd_base + GICD_CTLR_NS, gicd_ctlr_s);
isb();
dsb();
aft_print(LOG_LEVEL_INFO, "agicd_ctlr_ns:0x%x\n", gicd_ctlr_s);
return OK;
} /* END: Modefied by y00300051, 2016/3/12 */
uint32_t gic_gicd_enable_g1s(uint32_t gicd_base)
{
uint32_t gicd_ctlr_s;
gicd_ctlr_s = (uint32_t)mmio_read_32(gicd_base + GICD_CTLR_S + (uint32_t)(0 << 2)); // 2:bit移位
gicd_ctlr_s |= gicd_ctlr_enablesgrp1;
mmio_write_32(gicd_base + GICD_CTLR_S + (uint32_t)(0 << 2), gicd_ctlr_s); // 2:bit移位
isb();
dsb();
aft_print(LOG_LEVEL_INFO, "ssgicd_ctlr_s:0x%x\n", gicd_ctlr_s);
return OK;
}
/*
GICD_CTLR_S Distributor的控制寄存器(安全操作) tab 0x0000 32 RW 0x00000030
gicd_ctlr_rwp 31 RO 0x0 "所有Re-Distributor、CPU对写GICD_CTLR的group使能位或者ARE,或写GICD_ICENABLERn是否可见。
0:所有后续模块对写相关寄存器已经全部可见;
1:所有后续模块对写相关寄存器还没全部可见。"
reserved 30:8 RO 0x000000 保留
gicd_ctlr_e1nwf 7 RW 0x0
"Enable “1 of N” Wake-up Functionality:
0:a processor that is asleep cannot be picked for 1 of N interrupts.
1:a processor that is asleep can be picked for 1 of N interrupts;"
gicd_ctlr_ds 6 RW 0x0
"安全去使能位
0:不允许非安全模式访问和修改group0相关寄存器。
1:允许非安全模式访问和修改group0相关寄存器;该寄存器允许从0变为1;不允许从1变为0;"
gicd_ctlr_are_ns 5 RO 0x1
"非安全中断亲和性路由使能控制。
0:非安全中断亲和性路由不使能;
1:非安全中断亲和性路由使能。
注意:硬件没有保证该bit不从会1变为0,需要软件保证该bit不从1变为0;
该寄存器同时被作为硬件遵循的规范GICV2、GICV3的版本指示,
该bit被固定位1,表示硬件只遵循GICV3规范。"
gicd_ctlr_are_s 4 RO 0x1
"安全中断亲和性路由使能控制。
0:安全中断亲和性路由不使能;
1:安全中断亲和性路由使能。 该寄存器同时被作为硬件遵循的规范GICV2、GICV3的版本指示,
该bit被固定位1,表示硬件只遵循GICV3规范。"
reserved 3 RO 0x0 保留
gicd_ctlr_enablesgrp1 2 RW 0x0
"Secure Group 1中断使能控制。
0:Secure Group 1中断不使能;
1:Secure Group 1中断使能。 "
gicd_ctlr_enablensgrp1 1 RW 0x0
"Non-Secure Group 1中断使能控制。
0:Non-Secure Group 1中断不使能;
1:Non-Secure Group 1中断使能。"
gicd_ctlr_enablegrp0 0 RW 0x0
"Secure Group 0中断使能控制。
0:Secure Group 0中断不使能;
1:Secure Group 0中断使能。"
*/
uint32_t gic_gicd_enable_are(uint32_t gicd_base)
{
uint32_t gicd_ctlr_s;
gicd_ctlr_s = (uint32_t)mmio_read_32(gicd_base + GICD_CTLR_S);
/* GICv3 need this
先关中断 :中断去使能 */
if (((gicd_ctlr_s & (uint32_t)(~gicd_ctlr_enablesgrp1)) != 0 ||
(gicd_ctlr_s & (uint32_t)(~gicd_ctlr_enablegrp0)) != 0 ||
(gicd_ctlr_s & (uint32_t)(~gicd_ctlr_enablensgrp1)) != 0)) {
gicd_ctlr_s &= ~(gicd_ctlr_enablesgrp1 | gicd_ctlr_enablegrp0 | gicd_ctlr_enablensgrp1);
mmio_write_32(gicd_base + GICD_CTLR_S, gicd_ctlr_s);
WARN("GICD_CTLR_S:Clr bit (gicd_ctlr_enablesgrp1 |"
"gicd_ctlr_enablegrp0 | gicd_ctlr_enablensgrp1)\n");
}
// 亲和性路由使能
gicd_ctlr_s |= (gicd_ctlr_are_s | gicd_ctlr_are_ns);
mmio_write_32(gicd_base + GICD_CTLR_S, gicd_ctlr_s);
isb();
dsb();
aft_print(LOG_LEVEL_INFO, "dsgicd_ctlr_s:0x%x\n", mmio_read_32(GICD_BASE + GICD_CTLR_S));
return OK;
}
这是中断优先级的相关代码,请结合进行分析,给出完整的结论