Browse Source

GIC: Introduce API to get interrupt ID

Acknowledging interrupt shall return a raw value from the interrupt
controller in which the actual interrupt ID may be encoded. Add a
platform API to extract the actual interrupt ID from the raw value
obtained from interrupt controller.

Document the new function. Also clarify the semantics of interrupt
acknowledge.

Change-Id: I818dad7be47661658b16f9807877d259eb127405
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
pull/1152/head
Jeenu Viswambharan 7 years ago
parent
commit
4ee8d0becd
  1. 16
      docs/platform-interrupt-controller-API.rst
  2. 13
      docs/porting-guide.rst
  3. 3
      include/drivers/arm/gicv3.h
  4. 1
      include/plat/common/platform.h
  5. 10
      plat/common/plat_gicv2.c
  6. 8
      plat/common/plat_gicv3.c

16
docs/platform-interrupt-controller-API.rst

@ -292,6 +292,22 @@ inserts to order memory updates before updating mask, then writes to the GIC
*Priority Mask Register*, and make sure memory updates are visible before
potential trigger due to mask update.
Function: unsigned int plat_ic_get_interrupt_id(unsigned int raw); [optional]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
Argument : unsigned int
Return : unsigned int
This API should extract and return the interrupt number from the raw value
obtained by the acknowledging the interrupt (read using
``plat_ic_acknowledge_interrupt()``). If the interrupt ID is invalid, this API
should return ``INTR_ID_UNAVAILABLE``.
In case of ARM standard platforms using GIC, the implementation of the API
masks out the interrupt ID field from the acknowledged value from GIC.
----
*Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.*

13
docs/porting-guide.rst

@ -2479,14 +2479,17 @@ Function : plat\_ic\_acknowledge\_interrupt() [mandatory]
Return : uint32_t
This API is used by the CPU to indicate to the platform IC that processing of
the highest pending interrupt has begun. It should return the id of the
interrupt which is being processed.
the highest pending interrupt has begun. It should return the raw, unmodified
value obtained from the interrupt controller when acknowledging an interrupt.
The actual interrupt number shall be extracted from this raw value using the API
`plat_ic_get_interrupt_id()`__.
.. __: platform-interrupt-controller-API.rst#function-unsigned-int-plat-ic-get-interrupt-id-unsigned-int-raw-optional
This function in ARM standard platforms using GICv2, reads the *Interrupt
Acknowledge Register* (``GICC_IAR``). This changes the state of the highest
priority pending interrupt from pending to active in the interrupt controller.
It returns the value read from the ``GICC_IAR``. This value is the id of the
interrupt whose state has been changed.
It returns the value read from the ``GICC_IAR``, unmodified.
In the case of ARM standard platforms using GICv3, if the API is invoked
from EL3, the function reads the system register ``ICC_IAR0_EL1``, *Interrupt
@ -2494,7 +2497,7 @@ Acknowledge Register group 0*. If the API is invoked from S-EL1, the function
reads the system register ``ICC_IAR1_EL1``, *Interrupt Acknowledge Register
group 1*. The read changes the state of the highest pending interrupt from
pending to active in the interrupt controller. The value read is returned
and is the id of the interrupt whose state has been changed.
unmodified.
The TSP uses this API to start processing of the secure physical timer
interrupt.

3
include/drivers/arm/gicv3.h

@ -245,6 +245,9 @@
#define GICR_NUM_REGS(reg_name) \
DIV_ROUND_UP_2EVAL(TOTAL_PCPU_INTR_NUM, (1 << reg_name ## _SHIFT))
/* Interrupt ID mask for HPPIR, AHPPIR, IAR and AIAR CPU Interface registers */
#define INT_ID_MASK 0xffffff
/*******************************************************************************
* This structure describes some of the implementation defined attributes of the
* GICv3 IP. It is used by the platform port to specify these attributes in order

1
include/plat/common/platform.h

@ -90,6 +90,7 @@ void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode,
void plat_ic_set_interrupt_pending(unsigned int id);
void plat_ic_clear_interrupt_pending(unsigned int id);
unsigned int plat_ic_set_priority_mask(unsigned int mask);
unsigned int plat_ic_get_interrupt_id(unsigned int raw);
/*******************************************************************************
* Optional common functions (may be overridden)

10
plat/common/plat_gicv2.c

@ -277,3 +277,13 @@ unsigned int plat_ic_set_priority_mask(unsigned int mask)
{
return gicv2_set_pmr(mask);
}
unsigned int plat_ic_get_interrupt_id(unsigned int raw)
{
unsigned int id = (raw & INT_ID_MASK);
if (id == GIC_SPURIOUS_INTERRUPT)
id = INTR_ID_UNAVAILABLE;
return id;
}

8
plat/common/plat_gicv3.c

@ -271,6 +271,14 @@ unsigned int plat_ic_set_priority_mask(unsigned int mask)
{
return gicv3_set_pmr(mask);
}
unsigned int plat_ic_get_interrupt_id(unsigned int raw)
{
unsigned int id = (raw & INT_ID_MASK);
return (gicv3_is_intr_id_special_identifier(id) ?
INTR_ID_UNAVAILABLE : id);
}
#endif
#ifdef IMAGE_BL32

Loading…
Cancel
Save