I am using Linaro's Android release on Juno r1. I noticed that there are 6 user push buttons on the board, and I am trying to use the buttons to trigger a world switch (from non-secure to secure).
Firstly I found the interrupt id for the push buttons on SoC maunal, it seems that all 6 buttons share the same interrupt id 195. Then I added the following lines to configure the interrupt 195 to be a secure interrupt,
file: arm-tf/drivers/arm/gic/arm_gic.c
function: arm_gic_distif_setup
gicd_set_igroupr(g_gicd_base, 195); gicd_set_isenabler(g_gicd_base, 195);
After that, i thought that the interrupt should be routed to EL3 first. And also, to learn how the secure interrupt works, i added logs in all functions in arm-tf/plat/common/plat_gic.c. However, when i press the buttons, nothing happened.
My first question is what is the difference between the "Interrupt ID" and the "GIC IRQ ID" listed in the Juno Technical Reference Manual, Table 2-5. They are different values, and i am a litter confusion about it.
Then about the GICD_IGROUPR. From the GIC manual, the description of GICD_IGROUPR tells that these registers works for interrupt 0-31. So the interrupt 195 is out of the scope. What is the correct way to
route the interrupt of push buttons to EL3?
Thanks for any help!
Regards,
Zhenyu
Hi,
It seems you've slightly misunderstood how the GIC works.
gicd_set_igroupr(g_gicd_base, 195);
This call to the gicd_set_igroupr() function will make interrupt ID 195 be Group 1, which is actually the opposite of what you want.
You want the interrupt to be Group 0 (by instead calling gicd_clr_igroupr()), with Group 0 interrupts signalled as FIQs (by setting GICD_CTLR.FIQEn), and FIQs routed to EL3 (by setting SCR_EL3.FIQ). By default Trusted Firmware already does the latter two.
Which version of the Technical Reference Manual are you using?
I'm using ARM DDI 0515F, which shows the interrupt mapping in Table 3-4, not Table 2-5 and also doesn't show a "GIC IRQ ID". What values are shown in your version of the TRM? If I had to take a guess, the "GIC IRQ ID" may be referring to the "SPI ID" which would be the Interrupt ID minus 32 (SPIs start at Interrupt ID 32). The "correct" value to use for the GIC driver functions is the Interrupt ID.
Then about the GICD_IGROUPR. From the GIC manual, the description of GICD_IGROUPR tells that these registers works for interrupt 0-31. So the interrupt 195 is out of the scope. What is the correct way toroute the interrupt of push buttons to EL3?
There are actually up to 32 separate GICD_IGROUPR registers, numbered [0..31] inclusive, i.e. GICD_IGROUPR0, GICD_IGROUPR1, ..., GICD_IGROUPR31, where each bit corresponds to the Group of a single Interrupt ID.
For a given interrupt ID (let's say 195 since that's the one you're using), the corresponding GICD_IGROUPR register is (195 / 32) = 6, and the corresponding bit in that register is (195 % 32) = 3.
So, clearing bit [3] of GICD_IGROUPR6 will make Interrupt ID 195 be Group 0, while setting the bit will make it be Group 1.
This same logic applies to other per-interrupt registers, such as GICD_ISENABLER, GICD_IPRIORITYR, GICD_ITARGETSR, etc, though in the case of the latter two registers each field is 8 bits rather than 1 bit, so the correct register and field number is calculated as (195 / 4) and (195 % 4) because there are 4 fields per register rather than 32 fields per register.
Hope that helps,
Ash
Thanks Ash!! You totally solved my confusion about GICD_IGROUPR, really appreciate for it! I was wondering how a 32-bit length register could support up to 1019 interrupts all the time, now I got it.
However, it makes me feel sad that it still does not work.
Firstly, about the GIC IRQ ID, i found it in the "ARM Versatile Express Juno Development Platform (V2M-Juno) Technical Reference Manual", 0000-03. I guess you are totally correct, and the GIC IRQ ID is equal to Interrupt ID minus 32.
And i am sorry for the serious mistake on gicd_set_igroupr and gicd_clr_igroupr. I corrected that and double checked the values by DS-5. From DS-5, i can verify that the value of GICD_IGROUPR6 is 0xfffffff7, which means interrupt 195 should in group 0 now. Also I checked GICD_CTLR, the value is 0x00000003, which means both group 0 and group 1 should be enabled. Moreover, the value of GICC_CTLR is 0x000001EB, which indicates that the FIQEn bit is set. However, the SCR_EL3.FIQ is not set by default, and I set it in function "cm_init_context_common" of file "arm-tf/bl31/context_mgmt.c". After that, I guess all the prerequisite registers are configured.
But when i press the buttons on Juno, nothing happened at all. As i am trying to learn how the interrupt is handled in BL31, i added logs on entrance of each function in file "arm-tf/plat/common/plat_gic.c", but it seems that none of those functions is invoked. Am I still missing something?
Thanks again for your help!
View all questions in Arm Development Platforms forum