This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

I need support to initialize GICv2 on ARM A53 Dual Core processor environment in Non Secure mode.

Hi, I'm trying to initialize the GICv2 interrupt controller to manage interrupts coming in the systems.

At the moment I'm not able to receive interrupts on the CPU.

It seems to me that these interrupts are pending only in case I have Group0 enabled (GICD_CTRL.bit0) but when I have Group1 enabled (GICD_CTRL.bit1) these are not propagated.

To see interrupt pending I'm looking at register GICD_ISPENDRn.

This is the first time I'm programming GICv2 and I'm using low level code.

Can you support on this?

Do you have a sequence of programming operations to be implemented for the configuration in Non Secure mode?

At the moment I'm considering the GICv2 interrupt controller but probably I need to enable the interrupts on the A53 (Core0).

Thanks a lot for your support.

Best regards Edo.

Parents
  • I've tried to write out a few suggestions, hope they help.

    In GICv2, interrupts are either Group 0 (Secure) or Group 1(Non-secure). Which Group an INTID belongs to is controlled by GICD_IGROUPRn, which is only accessible to Secure software.  At reset, all interrupts are assigned to Group 0.  Group 0 interrupts will be signalled as FIQs, Group 1 as IRQs.

    To enable interrupts you need to:

    • Set the Group enables in GICD_CTLR
      • As you've seen, there is an enable per Group.  If you only set the G0 enable, only interrupts configured as G0 will be singable (for example).  Only Secure writes can set the G0 enable.  The G1 enable can be set be Secure or Non-secure writes.
    • For each CPU connect to the GIC
      • Set the Group enables in GICC_CTLR
        • Again, it's per Group.  If you only set (for example) the G1 enable, that CPU would only be able to receive interrupts marked as G1.  Only Secure writes can set the G0 enable.  The G1 enable can be set be Secure or Non-secure writes.
      • Also in GICC_CTLR, make sure you have FIQen set to 1
      • Set the Priority Mask, GICC_PMR
        • This sets the minimum priority for interrupts to be signalled to this CPU.  An interrupt must be *higher* priority than the mask to be signalled. In GIC, the lower the numeric value, the higher the priority.  This register resets to 0x0, which means ALL interrupts are masked.  Using a Secure write you need to set it something other than 0.  If this is a simple test case, I'd suggesting writing 0xFF to it,
    • For each interrupt you are using:
      • Set the Group, GICD_IGROUPRn
      • Set the target, GICD_ITARGETSRn  (only needed for SPIs, so INTIDs 32 and up)
      • Set the priority, GICD_IPRIORITY (remember, this must be sufficient to beat the PMR value you set up)
      • Set the enable, GICD_ISENABLERn

    There are also some things you need to set up on the CPU itself:

    • Set the Vector table(s) location, VBAR_ELn
    • Set the routing controls, SCR_EL3.IRQ/FIQ and HCR_EL2.IMO/FMO.  These control which Exception level (EL) interrupts are taken to.  If you set the target EL to one that is lower than the current EL, the interrupt is masked.  For example, if IRQs are routed to EL1, but you're currently in EL3, IRQs will be masked by the CPU.
    • Clear the PSTATE interrupt masks for the interrupts you want to take (e.g. PSTATE.I for IRQs, PSTATE.F for FIQs)
Reply
  • I've tried to write out a few suggestions, hope they help.

    In GICv2, interrupts are either Group 0 (Secure) or Group 1(Non-secure). Which Group an INTID belongs to is controlled by GICD_IGROUPRn, which is only accessible to Secure software.  At reset, all interrupts are assigned to Group 0.  Group 0 interrupts will be signalled as FIQs, Group 1 as IRQs.

    To enable interrupts you need to:

    • Set the Group enables in GICD_CTLR
      • As you've seen, there is an enable per Group.  If you only set the G0 enable, only interrupts configured as G0 will be singable (for example).  Only Secure writes can set the G0 enable.  The G1 enable can be set be Secure or Non-secure writes.
    • For each CPU connect to the GIC
      • Set the Group enables in GICC_CTLR
        • Again, it's per Group.  If you only set (for example) the G1 enable, that CPU would only be able to receive interrupts marked as G1.  Only Secure writes can set the G0 enable.  The G1 enable can be set be Secure or Non-secure writes.
      • Also in GICC_CTLR, make sure you have FIQen set to 1
      • Set the Priority Mask, GICC_PMR
        • This sets the minimum priority for interrupts to be signalled to this CPU.  An interrupt must be *higher* priority than the mask to be signalled. In GIC, the lower the numeric value, the higher the priority.  This register resets to 0x0, which means ALL interrupts are masked.  Using a Secure write you need to set it something other than 0.  If this is a simple test case, I'd suggesting writing 0xFF to it,
    • For each interrupt you are using:
      • Set the Group, GICD_IGROUPRn
      • Set the target, GICD_ITARGETSRn  (only needed for SPIs, so INTIDs 32 and up)
      • Set the priority, GICD_IPRIORITY (remember, this must be sufficient to beat the PMR value you set up)
      • Set the enable, GICD_ISENABLERn

    There are also some things you need to set up on the CPU itself:

    • Set the Vector table(s) location, VBAR_ELn
    • Set the routing controls, SCR_EL3.IRQ/FIQ and HCR_EL2.IMO/FMO.  These control which Exception level (EL) interrupts are taken to.  If you set the target EL to one that is lower than the current EL, the interrupt is masked.  For example, if IRQs are routed to EL1, but you're currently in EL3, IRQs will be masked by the CPU.
    • Clear the PSTATE interrupt masks for the interrupts you want to take (e.g. PSTATE.I for IRQs, PSTATE.F for FIQs)
Children