[PATCH 3/5] bsp/qoriq: Support message signaled interrupts

Sebastian Huber sebastian.huber at embedded-brains.de
Thu Dec 22 10:23:40 UTC 2022


---
 bsps/powerpc/qoriq/include/bsp/irq.h |  48 ++++--
 bsps/powerpc/qoriq/irq/irq.c         | 233 +++++++++++++++++++++++++--
 2 files changed, 255 insertions(+), 26 deletions(-)

diff --git a/bsps/powerpc/qoriq/include/bsp/irq.h b/bsps/powerpc/qoriq/include/bsp/irq.h
index 0f1581542e..8f73c6f3de 100644
--- a/bsps/powerpc/qoriq/include/bsp/irq.h
+++ b/bsps/powerpc/qoriq/include/bsp/irq.h
@@ -331,15 +331,15 @@ extern "C" {
  * @{
  */
 
-#define QORIQ_IRQ_MSI_BASE (QORIQ_IRQ_MI_7 + 1)
-#define QORIQ_IRQ_MSI_0 (QORIQ_IRQ_MSI_BASE + 0)
-#define QORIQ_IRQ_MSI_1 (QORIQ_IRQ_MSI_BASE + 1)
-#define QORIQ_IRQ_MSI_2 (QORIQ_IRQ_MSI_BASE + 2)
-#define QORIQ_IRQ_MSI_3 (QORIQ_IRQ_MSI_BASE + 3)
-#define QORIQ_IRQ_MSI_4 (QORIQ_IRQ_MSI_BASE + 4)
-#define QORIQ_IRQ_MSI_5 (QORIQ_IRQ_MSI_BASE + 5)
-#define QORIQ_IRQ_MSI_6 (QORIQ_IRQ_MSI_BASE + 6)
-#define QORIQ_IRQ_MSI_7 (QORIQ_IRQ_MSI_BASE + 7)
+#define QORIQ_IRQ_MSI_MULTIPLEX_BASE (QORIQ_IRQ_MI_7 + 1)
+#define QORIQ_IRQ_MSI_0 (QORIQ_IRQ_MSI_MULTIPLEX_BASE + 0)
+#define QORIQ_IRQ_MSI_1 (QORIQ_IRQ_MSI_MULTIPLEX_BASE + 1)
+#define QORIQ_IRQ_MSI_2 (QORIQ_IRQ_MSI_MULTIPLEX_BASE + 2)
+#define QORIQ_IRQ_MSI_3 (QORIQ_IRQ_MSI_MULTIPLEX_BASE + 3)
+#define QORIQ_IRQ_MSI_4 (QORIQ_IRQ_MSI_MULTIPLEX_BASE + 4)
+#define QORIQ_IRQ_MSI_5 (QORIQ_IRQ_MSI_MULTIPLEX_BASE + 5)
+#define QORIQ_IRQ_MSI_6 (QORIQ_IRQ_MSI_MULTIPLEX_BASE + 6)
+#define QORIQ_IRQ_MSI_7 (QORIQ_IRQ_MSI_MULTIPLEX_BASE + 7)
 
 /** @} */
 
@@ -363,7 +363,25 @@ extern "C" {
 #define QORIQ_IRQ_GT_B_2 (QORIQ_IRQ_GT_BASE + 6)
 #define QORIQ_IRQ_GT_B_3 (QORIQ_IRQ_GT_BASE + 7)
 
-#define BSP_INTERRUPT_VECTOR_COUNT (QORIQ_IRQ_GT_B_3 + 1)
+#define QORIQ_INTERRUPT_SOURCE_COUNT (QORIQ_IRQ_GT_B_3 + 1)
+
+#define QORIQ_IS_INTERRUPT_SOURCE(vector) \
+  (((rtems_vector_number) (vector)) < QORIQ_INTERRUPT_SOURCE_COUNT)
+
+#define QORIQ_IRQ_MSI_BASE QORIQ_INTERRUPT_SOURCE_COUNT
+
+#define QORIQ_IRQ_MSI_COUNT 256
+
+#define QORIQ_IRQ_MSI_INDEX(vector) ((vector) - QORIQ_IRQ_MSI_BASE)
+
+#define QORIQ_IRQ_MSI_VECTOR(index) (QORIQ_IRQ_MSI_BASE + (index))
+
+#define QORIQ_IRQ_MSI_REGISTER(vector) (QORIQ_IRQ_MSI_INDEX(vector) / 32)
+
+#define QORIQ_IRQ_IS_MSI(vector) \
+  (QORIQ_IRQ_MSI_INDEX(vector) < QORIQ_IRQ_MSI_COUNT)
+
+#define BSP_INTERRUPT_VECTOR_COUNT QORIQ_IRQ_MSI_VECTOR(QORIQ_IRQ_MSI_COUNT)
 
 /** @} */
 
@@ -403,6 +421,16 @@ rtems_status_code bsp_interrupt_get_affinity(
   Processor_mask *affinity
 );
 
+rtems_status_code qoriq_pic_msi_allocate(rtems_vector_number *vector);
+
+rtems_status_code qoriq_pic_msi_free(rtems_vector_number vector);
+
+rtems_status_code qoriq_pic_msi_map(
+  rtems_vector_number vector,
+  uint64_t *addr,
+  uint32_t *data
+);
+
 /** @} */
 
 #ifdef __cplusplus
diff --git a/bsps/powerpc/qoriq/irq/irq.c b/bsps/powerpc/qoriq/irq/irq.c
index f33b7c24ae..81eb742b5d 100644
--- a/bsps/powerpc/qoriq/irq/irq.c
+++ b/bsps/powerpc/qoriq/irq/irq.c
@@ -34,6 +34,7 @@
  */
 
 #include <sys/param.h>
+#include <sys/bitset.h>
 
 #include <rtems.h>
 
@@ -307,6 +308,10 @@ rtems_status_code qoriq_pic_set_priority(
 	rtems_status_code sc = RTEMS_SUCCESSFUL;
 	uint32_t old_vpr = 0;
 
+	if (QORIQ_IRQ_IS_MSI(vector)) {
+		return RTEMS_UNSATISFIED;
+	}
+
 	if (bsp_interrupt_is_valid_vector(vector)) {
 		volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
 
@@ -344,6 +349,10 @@ rtems_status_code bsp_interrupt_set_affinity(
 		return RTEMS_UNSATISFIED;
 	}
 
+	if (QORIQ_IRQ_IS_MSI(vector)) {
+		return RTEMS_UNSATISFIED;
+	}
+
 	src_cfg = get_src_cfg(vector);
 	src_cfg->dr = _Processor_mask_To_uint32_t(affinity, 0);
 	return RTEMS_SUCCESSFUL;
@@ -360,22 +369,34 @@ rtems_status_code bsp_interrupt_get_affinity(
 		return RTEMS_UNSATISFIED;
 	}
 
+	if (QORIQ_IRQ_IS_MSI(vector)) {
+		return RTEMS_UNSATISFIED;
+	}
+
 	src_cfg = get_src_cfg(vector);
 	_Processor_mask_From_uint32_t(affinity, src_cfg->dr, 0);
 	return RTEMS_SUCCESSFUL;
 }
 
-static void pic_vector_enable(rtems_vector_number vector, uint32_t msk)
+static rtems_status_code pic_vector_set_mask(
+	rtems_vector_number vector,
+	uint32_t msk
+)
 {
 	volatile qoriq_pic_src_cfg *src_cfg;
 	rtems_interrupt_lock_context lock_context;
 
 	bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
 
+	if (QORIQ_IRQ_IS_MSI(vector)) {
+		return RTEMS_UNSATISFIED;
+	}
+
 	src_cfg = get_src_cfg(vector);
 	rtems_interrupt_lock_acquire(&lock, &lock_context);
 	src_cfg->vpr = (src_cfg->vpr & ~VPR_MSK) | msk;
 	rtems_interrupt_lock_release(&lock, &lock_context);
+	return RTEMS_SUCCESSFUL;
 }
 
 rtems_status_code bsp_interrupt_get_attributes(
@@ -383,17 +404,25 @@ rtems_status_code bsp_interrupt_get_attributes(
 	rtems_interrupt_attributes *attributes
 )
 {
-	bool vector_is_ipi = pic_is_ipi(vector);
+	bool is_ipi = pic_is_ipi(vector);
+	bool is_msi_x = QORIQ_IRQ_IS_MSI(vector);
+
 	attributes->is_maskable = true;
-	attributes->can_enable = true;
-	attributes->maybe_enable = true;
-	attributes->can_disable = true;
-	attributes->maybe_disable = true;
+	attributes->can_enable = !is_msi_x;
+	attributes->maybe_enable = !is_msi_x;
+	attributes->can_disable = !is_msi_x;
+	attributes->maybe_disable = !is_msi_x;
 	attributes->cleared_by_acknowledge = true;
-	attributes->can_get_affinity = !vector_is_ipi;
-	attributes->can_set_affinity = !vector_is_ipi;
-	attributes->can_raise = vector_is_ipi;
-	attributes->can_raise_on = vector_is_ipi;
+	attributes->can_get_affinity = !(is_ipi || is_msi_x);
+	attributes->can_set_affinity = !(is_ipi || is_msi_x);
+	attributes->can_raise = is_ipi;
+	attributes->can_raise_on = is_ipi;
+
+	if (is_msi_x) {
+		attributes->can_be_triggered_by_message = true;
+		attributes->trigger_signal = RTEMS_INTERRUPT_NO_SIGNAL;
+	}
+
 	return RTEMS_SUCCESSFUL;
 }
 
@@ -407,6 +436,11 @@ rtems_status_code bsp_interrupt_is_pending(
 	bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
 	bsp_interrupt_assert(pending != NULL);
 
+	if (QORIQ_IRQ_IS_MSI(vector)) {
+		*pending = false;
+		return RTEMS_SUCCESSFUL;
+	}
+
 	src_cfg = get_src_cfg(vector);
 	*pending = (src_cfg->vpr & VPR_A) != 0;
 	return RTEMS_SUCCESSFUL;
@@ -463,6 +497,10 @@ rtems_status_code bsp_interrupt_vector_is_enabled(
 	bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
 	bsp_interrupt_assert(enabled != NULL);
 
+	if (QORIQ_IRQ_IS_MSI(vector)) {
+		vector = QORIQ_IRQ_MSI_0 + QORIQ_IRQ_MSI_REGISTER(vector);
+	}
+
 	src_cfg = get_src_cfg(vector);
 	*enabled = (src_cfg->vpr & VPR_MSK) == 0;
 	return RTEMS_SUCCESSFUL;
@@ -470,14 +508,12 @@ rtems_status_code bsp_interrupt_vector_is_enabled(
 
 rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
 {
-	pic_vector_enable(vector, 0);
-	return RTEMS_SUCCESSFUL;
+	return pic_vector_set_mask(vector, 0);
 }
 
 rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
 {
-	pic_vector_enable(vector, VPR_MSK);
-	return RTEMS_SUCCESSFUL;
+	return pic_vector_set_mask(vector, VPR_MSK);
 }
 
 void bsp_interrupt_dispatch(uintptr_t exception_number)
@@ -529,7 +565,7 @@ void bsp_interrupt_facility_initialize(void)
 
 		pic_reset();
 
-		for (i = 0; i < BSP_INTERRUPT_VECTOR_COUNT; ++i) {
+		for (i = 0; i < QORIQ_INTERRUPT_SOURCE_COUNT; ++i) {
 			volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(i);
 
 			src_cfg->vpr = VPR_MSK | VPR_P
@@ -555,11 +591,176 @@ void bsp_interrupt_facility_initialize(void)
 
 	qoriq.pic.ctpr = 0;
 
-	for (i = 0; i < BSP_INTERRUPT_VECTOR_COUNT; ++i) {
+	for (i = 0; i < QORIQ_INTERRUPT_SOURCE_COUNT; ++i) {
 		qoriq.pic.iack;
 		qoriq.pic.eoi = 0;
 		qoriq.pic.whoami;
 	}
 }
 
+typedef __BITSET_DEFINE(pic_msi_bitset, QORIQ_IRQ_MSI_COUNT) pic_msi_bitset;
+
+static pic_msi_bitset pic_msi_available =
+  __BITSET_T_INITIALIZER(__BITSET_FSET(__bitset_words(QORIQ_IRQ_MSI_COUNT)));
+
+
+static uint32_t pic_msi_bitset_to_uint32_t(
+	const pic_msi_bitset *bitset,
+	uint32_t              index
+)
+{
+	long bits = bitset->__bits[index / _BITSET_BITS];
+
+	return (uint32_t) (bits >> (32 * ((index % _BITSET_BITS) / 32)));
+}
+
+static void pic_msi_dispatch(void *arg)
+{
+	uintptr_t reg = (uintptr_t) arg;
+	uint32_t msir = qoriq.pic.msir[reg].reg;
+
+	while (msir != 0) {
+		uint32_t index = 31 - __builtin_clz(msir);
+		const rtems_interrupt_entry *entry;
+
+		msir &= ~(UINT32_C(1) << index);
+		entry = bsp_interrupt_entry_load_first(
+			QORIQ_IRQ_MSI_VECTOR(32 * reg + index)
+		);
+
+		if (entry != NULL) {
+			bsp_interrupt_dispatch_entries(entry);
+		}
+	}
+}
+
+static rtems_status_code pic_msi_allocate(rtems_vector_number *vector)
+{
+	pic_msi_bitset *available = &pic_msi_available;
+	long found = __BIT_FFS(QORIQ_IRQ_MSI_COUNT, available);
+	rtems_vector_number index;
+	uint32_t subset;
+
+	if (found == 0) {
+		return RTEMS_UNSATISFIED;
+	}
+
+	index = (rtems_vector_number) found - 1;
+	subset = pic_msi_bitset_to_uint32_t(available, index);
+
+	if (subset == 0xffffffff) {
+		uintptr_t reg = index / 32;
+		rtems_status_code sc;
+
+		sc = rtems_interrupt_handler_install(
+			QORIQ_IRQ_MSI_0 + reg,
+			"MSI",
+			RTEMS_INTERRUPT_UNIQUE,
+			pic_msi_dispatch,
+			(void *) reg
+		);
+
+		if (sc != RTEMS_SUCCESSFUL) {
+			return sc;
+		}
+	}
+
+	__BIT_CLR(QORIQ_IRQ_MSI_COUNT, index, available);
+	*vector = QORIQ_IRQ_MSI_VECTOR(index);
+	return RTEMS_SUCCESSFUL;
+}
+
+static rtems_status_code pic_msi_free(rtems_vector_number vector)
+{
+	pic_msi_bitset *available = &pic_msi_available;
+	rtems_vector_number index = QORIQ_IRQ_MSI_INDEX(vector);
+	uint32_t subset;
+
+	if (__BIT_ISSET(QORIQ_IRQ_MSI_COUNT, index, available)) {
+		return RTEMS_NOT_DEFINED;
+	}
+
+	__BIT_SET(QORIQ_IRQ_MSI_COUNT, index, available);
+	subset = pic_msi_bitset_to_uint32_t(available, index);
+
+	if (subset == 0xffffffff) {
+		uintptr_t reg = index / 32;
+
+		return rtems_interrupt_handler_remove(
+			QORIQ_IRQ_MSI_0 + reg,
+			pic_msi_dispatch,
+			(void *) reg
+		);
+	}
+
+	return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code qoriq_pic_msi_allocate(rtems_vector_number *vector)
+{
+	rtems_status_code sc;
+
+	if (!bsp_interrupt_is_initialized()) {
+		return RTEMS_INCORRECT_STATE;
+	}
+
+	if (vector == NULL) {
+		return RTEMS_INVALID_ADDRESS;
+	}
+
+	if (rtems_interrupt_is_in_progress()) {
+		return RTEMS_CALLED_FROM_ISR;
+	}
+
+	bsp_interrupt_lock();
+	sc = pic_msi_allocate(vector);
+	bsp_interrupt_unlock();
+	return sc;
+}
+
+rtems_status_code qoriq_pic_msi_free(rtems_vector_number vector)
+{
+	rtems_status_code sc;
+
+	if (!bsp_interrupt_is_initialized()) {
+		return RTEMS_INCORRECT_STATE;
+	}
+
+	if (!QORIQ_IRQ_IS_MSI(vector) ) {
+		return RTEMS_INVALID_ID;
+	}
+
+	if (rtems_interrupt_is_in_progress()) {
+		return RTEMS_CALLED_FROM_ISR;
+	}
+
+	bsp_interrupt_lock();
+	sc = pic_msi_free(vector);
+	bsp_interrupt_unlock();
+	return sc;
+}
+
+rtems_status_code qoriq_pic_msi_map(
+	rtems_vector_number vector,
+	uint64_t *addr,
+	uint32_t *data
+)
+{
+	if (addr == NULL) {
+		return RTEMS_INVALID_ADDRESS;
+	}
+
+	if (data == NULL) {
+		return RTEMS_INVALID_ADDRESS;
+	}
+
+	if (!QORIQ_IRQ_IS_MSI(vector) ) {
+		return RTEMS_INVALID_ID;
+	}
+
+	*addr = (uint64_t)(uintptr_t) &qoriq.pic.msiir;
+	*data = QORIQ_IRQ_MSI_INDEX(vector) << 24;
+	return RTEMS_SUCCESSFUL;
+}
+
 #endif /* QORIQ_IS_HYPERVISOR_GUEST */
-- 
2.35.3



More information about the devel mailing list