GICv2: Add driver API to set PE target mask
authorJeenu Viswambharan <jeenu.viswambharan@arm.com>
Fri, 22 Sep 2017 07:32:09 +0000 (08:32 +0100)
committerJeenu Viswambharan <jeenu.viswambharan@arm.com>
Mon, 16 Oct 2017 15:50:01 +0000 (16:50 +0100)
The PE target mask is used to translate linear PE index (returned by
platform core position) to a bit mask used when targeting interrupts to
a PE, viz. when raising SGIs and routing SPIs.

The platform shall:

  - Populate the driver data with a pointer to array that's to contain
    per-PE target masks.

  - Invoke the new driver API 'gicv2_set_pe_target_mask()' during
    per-CPU initialization so that the driver populates the target mask
    for that CPU.

Platforms that don't intend to target interrupts or raise SGIs need not
populate this.

Change-Id: Ic0db54da86915e9dccd82fff51479bc3c1fdc968
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
drivers/arm/gic/v2/gicv2_main.c
include/drivers/arm/gicv2.h

index 7759a551a65d499578f661deaf5d99db506bf524..28266807c25f1fd7d787c800c722eb2c6566cd6d 100644 (file)
@@ -252,3 +252,26 @@ unsigned int gicv2_get_running_priority(void)
 
        return gicc_read_rpr(driver_data->gicc_base);
 }
+
+/*******************************************************************************
+ * This function sets the GICv2 target mask pattern for the current PE. The PE
+ * target mask is used to translate linear PE index (returned by platform core
+ * position) to a bit mask used when targeting interrupts to a PE, viz. when
+ * raising SGIs and routing SPIs.
+ ******************************************************************************/
+void gicv2_set_pe_target_mask(unsigned int proc_num)
+{
+       assert(driver_data);
+       assert(driver_data->gicd_base);
+       assert(driver_data->target_masks);
+       assert(proc_num < GICV2_MAX_TARGET_PE);
+       assert(proc_num < driver_data->target_masks_num);
+
+       /* Return if the target mask is already populated */
+       if (driver_data->target_masks[proc_num])
+               return;
+
+       /* Read target register corresponding to this CPU */
+       driver_data->target_masks[proc_num] =
+               gicv2_get_cpuif_id(driver_data->gicd_base);
+}
index 1ef0779b99c4a3df572bb8091a3e2682bda17850..c91cc1b049cc3b8293241892ca611b886734b4ca 100644 (file)
@@ -13,6 +13,9 @@
 /* Interrupt IDs reported by the HPPIR and IAR registers */
 #define PENDING_G1_INTID       1022
 
+/* GICv2 can only target up to 8 PEs */
+#define GICV2_MAX_TARGET_PE    8
+
 /*******************************************************************************
  * GICv2 specific Distributor interface register offsets and constants.
  ******************************************************************************/
  * in order to initialize the GICv2 driver. The attributes are described
  * below.
  *
- * 1. The 'gicd_base' field contains the base address of the Distributor
- *    interface programmer's view.
+ * The 'gicd_base' field contains the base address of the Distributor interface
+ * programmer's view.
+ *
+ * The 'gicc_base' field contains the base address of the CPU Interface
+ * programmer's view.
  *
- * 2. The 'gicc_base' field contains the base address of the CPU Interface
- *    programmer's view.
+ * The 'g0_interrupt_array' field is a pointer to an array in which each
+ * entry corresponds to an ID of a Group 0 interrupt.
  *
- * 3. The 'g0_interrupt_array' field is a pointer to an array in which each
- *    entry corresponds to an ID of a Group 0 interrupt.
+ * The 'g0_interrupt_num' field contains the number of entries in the
+ * 'g0_interrupt_array'.
  *
- * 4. The 'g0_interrupt_num' field contains the number of entries in the
- *    'g0_interrupt_array'.
+ * The 'target_masks' is a pointer to an array containing 'target_masks_num'
+ * elements. The GIC driver will populate the array with per-PE target mask to
+ * use to when targeting interrupts.
  ******************************************************************************/
 typedef struct gicv2_driver_data {
        uintptr_t gicd_base;
        uintptr_t gicc_base;
        unsigned int g0_interrupt_num;
        const unsigned int *g0_interrupt_array;
+       unsigned int *target_masks;
+       unsigned int target_masks_num;
 } gicv2_driver_data_t;
 
 /*******************************************************************************
@@ -137,6 +146,7 @@ unsigned int gicv2_acknowledge_interrupt(void);
 void gicv2_end_of_interrupt(unsigned int id);
 unsigned int gicv2_get_interrupt_group(unsigned int id);
 unsigned int gicv2_get_running_priority(void);
+void gicv2_set_pe_target_mask(unsigned int proc_num);
 
 #endif /* __ASSEMBLY__ */
 #endif /* __GICV2_H__ */