[PATCH v2] bsps/irq: Implement new directives for GICv2/3

Sebastian Huber sebastian.huber at embedded-brains.de
Wed Jul 14 11:54:55 UTC 2021


Update #3269.
---
 bsps/include/dev/irq/arm-gic-irq.h |   3 +
 bsps/shared/dev/irq/arm-gicv2.c    |  83 +++++++++++++++----
 bsps/shared/dev/irq/arm-gicv3.c    | 125 +++++++++++++++++++++++++----
 3 files changed, 180 insertions(+), 31 deletions(-)

diff --git a/bsps/include/dev/irq/arm-gic-irq.h b/bsps/include/dev/irq/arm-gic-irq.h
index 68e0247fd8..398fd8bceb 100644
--- a/bsps/include/dev/irq/arm-gic-irq.h
+++ b/bsps/include/dev/irq/arm-gic-irq.h
@@ -46,6 +46,9 @@ extern "C" {
 #define ARM_GIC_IRQ_SGI_13 13
 #define ARM_GIC_IRQ_SGI_14 14
 #define ARM_GIC_IRQ_SGI_15 15
+#define ARM_GIC_IRQ_SGI_LAST 15
+
+#define ARM_GIC_IRQ_PPI_LAST 31
 
 #define ARM_GIC_DIST ((volatile gic_dist *) BSP_ARM_GIC_DIST_BASE)
 
diff --git a/bsps/shared/dev/irq/arm-gicv2.c b/bsps/shared/dev/irq/arm-gicv2.c
index a1ba5e9112..83422218da 100644
--- a/bsps/shared/dev/irq/arm-gicv2.c
+++ b/bsps/shared/dev/irq/arm-gicv2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2019 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2013, 2021 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
  *  Dornierstr. 4
@@ -69,6 +69,28 @@ rtems_status_code bsp_interrupt_get_attributes(
   rtems_interrupt_attributes *attributes
 )
 {
+  attributes->is_maskable = true;
+  attributes->maybe_enable = true;
+  attributes->maybe_disable = true;
+
+  if ( vector <= ARM_GIC_IRQ_SGI_LAST ) {
+    attributes->can_cause = true;
+    attributes->can_cause_on = true;
+    attributes->cleared_by_acknowledge = true;
+    attributes->trigger_signal = RTEMS_INTERRUPT_NO_SIGNAL;
+  } else {
+    attributes->can_disable = true;
+    attributes->can_cause = true;
+    attributes->can_clear = true;
+    attributes->trigger_signal = RTEMS_INTERRUPT_UNSPECIFIED_SIGNAL;
+
+    if ( vector > ARM_GIC_IRQ_PPI_LAST ) {
+      /* SPI */
+      attributes->can_get_affinity = true;
+      attributes->can_set_affinity = true;
+    }
+  }
+
   return RTEMS_SUCCESSFUL;
 }
 
@@ -77,16 +99,25 @@ rtems_status_code bsp_interrupt_is_pending(
   bool               *pending
 )
 {
-  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
-  bsp_interrupt_assert(pending != NULL);
-  *pending = false;
-  return RTEMS_UNSATISFIED;
+  volatile gic_dist *dist = ARM_GIC_DIST;
+
+  *pending = gic_id_is_pending(dist, vector);
+  return RTEMS_SUCCESSFUL;
 }
 
 rtems_status_code bsp_interrupt_cause(rtems_vector_number vector)
 {
   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
-  return RTEMS_UNSATISFIED;
+
+  if (vector <= ARM_GIC_IRQ_SGI_LAST) {
+    arm_gic_trigger_sgi(vector, 1U << _SMP_Get_current_processor());
+  } else {
+    volatile gic_dist *dist = ARM_GIC_DIST;
+
+    gic_id_set_pending(dist, vector);
+  }
+
+  return RTEMS_SUCCESSFUL;
 }
 
 #if defined(RTEMS_SMP)
@@ -95,15 +126,27 @@ rtems_status_code bsp_interrupt_cause_on(
   uint32_t            cpu_index
 )
 {
-  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
-  return RTEMS_UNSATISFIED;
+  if (vector >= 16) {
+    return RTEMS_UNSATISFIED;
+  }
+
+  arm_gic_trigger_sgi(vector, 1U << cpu_index);
+  return RTEMS_SUCCESSFUL;
 }
 #endif
 
 rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
 {
+  volatile gic_dist *dist = ARM_GIC_DIST;
+
   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
-  return RTEMS_UNSATISFIED;
+
+  if (vector <= ARM_GIC_IRQ_SGI_LAST) {
+    return RTEMS_UNSATISFIED;
+  }
+
+  gic_id_clear_pending(dist, vector);
+  return RTEMS_SUCCESSFUL;
 }
 
 rtems_status_code bsp_interrupt_vector_is_enabled(
@@ -111,10 +154,13 @@ rtems_status_code bsp_interrupt_vector_is_enabled(
   bool               *enabled
 )
 {
+  volatile gic_dist *dist = ARM_GIC_DIST;
+
   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
   bsp_interrupt_assert(enabled != NULL);
-  *enabled = false;
-  return RTEMS_UNSATISFIED;
+
+  *enabled = gic_id_is_enabled(dist, vector);
+  return RTEMS_SUCCESSFUL;
 }
 
 rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
@@ -207,8 +253,8 @@ BSP_START_TEXT_SECTION void arm_gic_irq_initialize_secondary_cpu(void)
   dist->icdigr[0] = 0xffffffff;
 #endif
 
-  /* Initialize Peripheral Private Interrupts (PPIs) */
-  for (id = 0; id < 32; ++id) {
+  /* Initialize priority of SGIs and PPIs */
+  for (id = 0; id <= ARM_GIC_IRQ_PPI_LAST; ++id) {
     gic_id_set_priority(dist, id, PRIORITY_DEFAULT);
   }
 
@@ -300,6 +346,10 @@ rtems_status_code bsp_interrupt_set_affinity(
   volatile gic_dist *dist = ARM_GIC_DIST;
   uint8_t targets = (uint8_t) _Processor_mask_To_uint32_t(affinity, 0);
 
+  if ( vector <= ARM_GIC_IRQ_PPI_LAST ) {
+    return RTEMS_UNSATISFIED;
+  }
+
   gic_id_set_targets(dist, vector, targets);
   return RTEMS_SUCCESSFUL;
 }
@@ -310,8 +360,13 @@ rtems_status_code bsp_interrupt_get_affinity(
 )
 {
   volatile gic_dist *dist = ARM_GIC_DIST;
-  uint8_t targets = gic_id_get_targets(dist, vector);
+  uint8_t targets;
+
+  if ( vector <= ARM_GIC_IRQ_PPI_LAST ) {
+    return RTEMS_UNSATISFIED;
+  }
 
+  targets = gic_id_get_targets(dist, vector);
   _Processor_mask_From_uint32_t(affinity, targets, 0);
   return RTEMS_SUCCESSFUL;
 }
diff --git a/bsps/shared/dev/irq/arm-gicv3.c b/bsps/shared/dev/irq/arm-gicv3.c
index 8db3053ffd..b5b11c16f5 100644
--- a/bsps/shared/dev/irq/arm-gicv3.c
+++ b/bsps/shared/dev/irq/arm-gicv3.c
@@ -169,6 +169,28 @@ rtems_status_code bsp_interrupt_get_attributes(
   rtems_interrupt_attributes *attributes
 )
 {
+  attributes->is_maskable = true;
+  attributes->maybe_enable = true;
+  attributes->maybe_disable = true;
+
+  if ( vector <= ARM_GIC_IRQ_SGI_LAST ) {
+    attributes->can_cause = true;
+    attributes->can_cause_on = true;
+    attributes->cleared_by_acknowledge = true;
+    attributes->trigger_signal = RTEMS_INTERRUPT_NO_SIGNAL;
+  } else {
+    attributes->can_disable = true;
+    attributes->can_cause = true;
+    attributes->can_clear = true;
+    attributes->trigger_signal = RTEMS_INTERRUPT_UNSPECIFIED_SIGNAL;
+
+    if ( vector > ARM_GIC_IRQ_PPI_LAST ) {
+      /* SPI */
+      attributes->can_get_affinity = true;
+      attributes->can_set_affinity = true;
+    }
+  }
+
   return RTEMS_SUCCESSFUL;
 }
 
@@ -179,14 +201,39 @@ rtems_status_code bsp_interrupt_is_pending(
 {
   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
   bsp_interrupt_assert(pending != NULL);
-  *pending = false;
-  return RTEMS_UNSATISFIED;
+
+  if (vector <= ARM_GIC_IRQ_PPI_LAST) {
+    volatile gic_sgi_ppi *sgi_ppi =
+      gicv3_get_sgi_ppi(_SMP_Get_current_processor());
+
+    *pending = (sgi_ppi->icspispendr[0] & (1U << vector)) != 0;
+  } else {
+    volatile gic_dist *dist = ARM_GIC_DIST;
+
+    *pending = gic_id_is_pending(dist, vector);
+  }
+
+  return RTEMS_SUCCESSFUL;
 }
 
 rtems_status_code bsp_interrupt_cause(rtems_vector_number vector)
 {
   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
-  return RTEMS_UNSATISFIED;
+
+  if (vector <= ARM_GIC_IRQ_SGI_LAST) {
+    arm_gic_trigger_sgi(vector, 1U << _SMP_Get_current_processor());
+  } else if (vector <= ARM_GIC_IRQ_PPI_LAST) {
+    volatile gic_sgi_ppi *sgi_ppi =
+      gicv3_get_sgi_ppi(_SMP_Get_current_processor());
+
+    sgi_ppi->icspispendr[0] = 1U << vector;
+  } else {
+    volatile gic_dist *dist = ARM_GIC_DIST;
+
+    gic_id_set_pending(dist, vector);
+  }
+
+  return RTEMS_SUCCESSFUL;
 }
 
 #if defined(RTEMS_SMP)
@@ -195,15 +242,35 @@ rtems_status_code bsp_interrupt_cause_on(
   uint32_t            cpu_index
 )
 {
-  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
-  return RTEMS_UNSATISFIED;
+  if (vector >= 16) {
+    return RTEMS_UNSATISFIED;
+  }
+
+  arm_gic_trigger_sgi(vector, 1U << cpu_index);
+  return RTEMS_SUCCESSFUL;
 }
 #endif
 
 rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
 {
   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
-  return RTEMS_UNSATISFIED;
+
+  if (vector <= ARM_GIC_IRQ_SGI_LAST) {
+    return RTEMS_UNSATISFIED;
+  }
+
+  if ( vector <= ARM_GIC_IRQ_PPI_LAST ) {
+    volatile gic_sgi_ppi *sgi_ppi =
+      gicv3_get_sgi_ppi(_SMP_Get_current_processor());
+
+    sgi_ppi->icspicpendr[0] = 1U << vector;
+  } else {
+    volatile gic_dist *dist = ARM_GIC_DIST;
+
+    gic_id_clear_pending(dist, vector);
+  }
+
+  return RTEMS_SUCCESSFUL;
 }
 
 rtems_status_code bsp_interrupt_vector_is_enabled(
@@ -213,8 +280,19 @@ rtems_status_code bsp_interrupt_vector_is_enabled(
 {
   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
   bsp_interrupt_assert(enabled != NULL);
-  *enabled = false;
-  return RTEMS_UNSATISFIED;
+
+  if ( vector <= ARM_GIC_IRQ_PPI_LAST ) {
+    volatile gic_sgi_ppi *sgi_ppi =
+      gicv3_get_sgi_ppi(_SMP_Get_current_processor());
+
+    *enabled = (sgi_ppi->icspiser[0] & (1U << vector)) != 0;
+  } else {
+    volatile gic_dist *dist = ARM_GIC_DIST;
+
+    *enabled = gic_id_is_enabled(dist, vector);
+  }
+
+  return RTEMS_SUCCESSFUL;
 }
 
 rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
@@ -222,22 +300,24 @@ rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
 
   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
 
-  if (vector >= 32) {
+  if (vector > ARM_GIC_IRQ_PPI_LAST) {
     volatile gic_dist *dist = ARM_GIC_DIST;
+
     gic_id_enable(dist, vector);
   } else {
     volatile gic_sgi_ppi *sgi_ppi =
       gicv3_get_sgi_ppi(_SMP_Get_current_processor());
+
     /* Set interrupt group to 1 in the current security mode */
 #if defined(ARM_MULTILIB_ARCH_V4) || defined(AARCH64_IS_NONSECURE)
-    sgi_ppi->icspigrpr[0] |= 1 << (vector % 32);
-    sgi_ppi->icspigrpmodr[0] &= ~(1 << (vector % 32));
+    sgi_ppi->icspigrpr[0] |= 1U << vector;
+    sgi_ppi->icspigrpmodr[0] &= ~(1U << vector);
 #else
-    sgi_ppi->icspigrpr[0] &= ~(1 << (vector % 32));
-    sgi_ppi->icspigrpmodr[0] |= 1 << (vector % 32);
+    sgi_ppi->icspigrpr[0] &= ~(1U << vector);
+    sgi_ppi->icspigrpmodr[0] |= 1U << vector;
 #endif
     /* Set enable */
-    sgi_ppi->icspiser[0] = 1 << (vector % 32);
+    sgi_ppi->icspiser[0] = 1U << vector;
   }
 
   return RTEMS_SUCCESSFUL;
@@ -247,13 +327,15 @@ rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
 {
   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
 
-  if (vector >= 32) {
+  if (vector > ARM_GIC_IRQ_PPI_LAST) {
     volatile gic_dist *dist = ARM_GIC_DIST;
+
     gic_id_disable(dist, vector);
   } else {
     volatile gic_sgi_ppi *sgi_ppi =
       gicv3_get_sgi_ppi(_SMP_Get_current_processor());
-    sgi_ppi->icspicer[0] = 1 << (vector % 32);
+
+    sgi_ppi->icspicer[0] = 1U << vector;
   }
 
   return RTEMS_SUCCESSFUL;
@@ -407,6 +489,10 @@ rtems_status_code bsp_interrupt_set_affinity(
   volatile gic_dist *dist = ARM_GIC_DIST;
   uint8_t targets = (uint8_t) _Processor_mask_To_uint32_t(affinity, 0);
 
+  if ( vector <= ARM_GIC_IRQ_PPI_LAST ) {
+    return RTEMS_UNSATISFIED;
+  }
+
   gic_id_set_targets(dist, vector, targets);
   return RTEMS_SUCCESSFUL;
 }
@@ -417,8 +503,13 @@ rtems_status_code bsp_interrupt_get_affinity(
 )
 {
   volatile gic_dist *dist = ARM_GIC_DIST;
-  uint8_t targets = gic_id_get_targets(dist, vector);
+  uint8_t targets;
+
+  if ( vector <= ARM_GIC_IRQ_PPI_LAST ) {
+    return RTEMS_UNSATISFIED;
+  }
 
+  targets = gic_id_get_targets(dist, vector);
   _Processor_mask_From_uint32_t(affinity, targets, 0);
   return RTEMS_SUCCESSFUL;
 }
-- 
2.26.2



More information about the devel mailing list