[PATCH 27.0 1/3 v2] SPARC BSPs: implemented shared-irq using libbsp/shared layer

Daniel Hellstrom daniel at gaisler.com
Fri Apr 6 10:05:07 UTC 2012


The implementation use IRQ number instead of vector number since
some IRQs does not have a unique vector, for example the extended
interrupts all enter the same trap vector entry.

Added support for the LEON3 extended interrupt controller when using
the shared IRQ layer.

ERC32 patches untested.

Signed-off-by: Daniel Hellstrom <daniel at gaisler.com>
---
 c/src/lib/libbsp/sparc/Makefile.am                 |    3 +
 c/src/lib/libbsp/sparc/erc32/Makefile.am           |   16 ++++-
 c/src/lib/libbsp/sparc/erc32/include/bsp.h         |   75 +++++++++++++++++-
 c/src/lib/libbsp/sparc/erc32/include/bsp/irq.h     |   20 +++++
 c/src/lib/libbsp/sparc/erc32/include/erc32.h       |   17 ++++
 c/src/lib/libbsp/sparc/erc32/preinstall.am         |   12 +++
 .../lib/libbsp/sparc/erc32/startup/bsppredriver.c  |   25 ++++++
 c/src/lib/libbsp/sparc/leon2/Makefile.am           |   15 ++++-
 c/src/lib/libbsp/sparc/leon2/include/bsp.h         |   74 +++++++++++++++++
 c/src/lib/libbsp/sparc/leon2/include/bsp/irq.h     |   20 +++++
 c/src/lib/libbsp/sparc/leon2/include/leon.h        |   17 ++++
 c/src/lib/libbsp/sparc/leon2/preinstall.am         |   12 +++
 .../lib/libbsp/sparc/leon2/startup/bsppredriver.c  |   25 ++++++
 c/src/lib/libbsp/sparc/leon3/Makefile.am           |   16 ++++-
 c/src/lib/libbsp/sparc/leon3/amba/amba.c           |    6 ++
 c/src/lib/libbsp/sparc/leon3/include/bsp.h         |   74 +++++++++++++++++
 c/src/lib/libbsp/sparc/leon3/include/bsp/irq.h     |   36 +++++++++
 c/src/lib/libbsp/sparc/leon3/include/leon.h        |   28 +++++++
 c/src/lib/libbsp/sparc/leon3/preinstall.am         |   12 +++
 .../lib/libbsp/sparc/leon3/startup/bsppredriver.c  |   25 ++++++
 c/src/lib/libbsp/sparc/leon3/startup/eirq.c        |   25 ++++++
 c/src/lib/libbsp/sparc/shared/include/ambapp.h     |    2 +
 c/src/lib/libbsp/sparc/shared/irq/irq-shared.c     |   83 ++++++++++++++++++++
 23 files changed, 634 insertions(+), 4 deletions(-)
 create mode 100644 c/src/lib/libbsp/sparc/erc32/include/bsp/irq.h
 create mode 100644 c/src/lib/libbsp/sparc/erc32/startup/bsppredriver.c
 create mode 100644 c/src/lib/libbsp/sparc/leon2/include/bsp/irq.h
 create mode 100644 c/src/lib/libbsp/sparc/leon2/startup/bsppredriver.c
 create mode 100644 c/src/lib/libbsp/sparc/leon3/include/bsp/irq.h
 create mode 100644 c/src/lib/libbsp/sparc/leon3/startup/bsppredriver.c
 create mode 100644 c/src/lib/libbsp/sparc/leon3/startup/eirq.c
 create mode 100644 c/src/lib/libbsp/sparc/shared/irq/irq-shared.c

diff --git a/c/src/lib/libbsp/sparc/Makefile.am b/c/src/lib/libbsp/sparc/Makefile.am
index b1b6a22..4f445ba 100644
--- a/c/src/lib/libbsp/sparc/Makefile.am
+++ b/c/src/lib/libbsp/sparc/Makefile.am
@@ -12,6 +12,9 @@ EXTRA_DIST =
 EXTRA_DIST += shared/gnatcommon.c
 EXTRA_DIST += shared/start.S
 
+# Interrupt
+EXTRA_DIST += shared/irq/irq-shared.c
+
 # AMBA Plug&Play bus
 EXTRA_DIST += shared/include/ambapp.h
 EXTRA_DIST += shared/amba/ambapp.c
diff --git a/c/src/lib/libbsp/sparc/erc32/Makefile.am b/c/src/lib/libbsp/sparc/erc32/Makefile.am
index e70310d..615a3e0 100644
--- a/c/src/lib/libbsp/sparc/erc32/Makefile.am
+++ b/c/src/lib/libbsp/sparc/erc32/Makefile.am
@@ -33,7 +33,7 @@ libbsp_a_SOURCES =
 
 # startup
 libbsp_a_SOURCES += ../../shared/bspclean.c ../../shared/bsplibc.c \
-    ../../shared/bsppredriverhook.c ../../sparc/shared/bspgetworkarea.c \
+    startup/bsppredriver.c ../../sparc/shared/bspgetworkarea.c \
     ../../sparc/shared/bsppretaskinghook.c ../../shared/bsppost.c \
     ../../shared/bspstart.c ../../shared/bootcard.c ../../shared/bspinit.c \
     ../../shared/sbrk.c startup/setvec.c startup/spurious.c \
@@ -55,6 +55,20 @@ libbsp_a_SOURCES += ../../shared/clockdrv_shell.h
 # timer
 libbsp_a_SOURCES += timer/timer.c
 
+# IRQ
+include_bsp_HEADERS = \
+    ../../shared/include/irq-generic.h \
+    ../../shared/include/irq-info.h \
+    include/bsp/irq.h
+libbsp_a_SOURCES += \
+    ../../sparc/shared/irq/irq-shared.c \
+    ../../shared/src/irq-default-handler.c \
+    ../../shared/src/irq-generic.c \
+    ../../shared/src/irq-info.c \
+    ../../shared/src/irq-legacy.c \
+    ../../shared/src/irq-server.c \
+    ../../shared/src/irq-shell.c
+
 if HAS_SMP
 libbsp_a_SOURCES += ../../shared/smp/getcpuid.c ../../shared/smp/smp_stub.c \
     ../../shared/smp/bspsmp_wait_for.c
diff --git a/c/src/lib/libbsp/sparc/erc32/include/bsp.h b/c/src/lib/libbsp/sparc/erc32/include/bsp.h
index 70f1ce3..429157d 100644
--- a/c/src/lib/libbsp/sparc/erc32/include/bsp.h
+++ b/c/src/lib/libbsp/sparc/erc32/include/bsp.h
@@ -30,8 +30,8 @@ extern "C" {
 #include <rtems/iosupp.h>
 #include <erc32.h>
 #include <rtems/clockdrv.h>
-
 #include <rtems/console.h>
+#include <rtems/irq-extension.h>
 
 /*
  *  BSP provides its own Idle thread body
@@ -90,6 +90,79 @@ void bsp_spurious_initialize( void );
  */
 void *bsp_early_malloc(int size);
 
+/* Interrupt Service Routine (ISR) pointer */
+typedef void (*bsp_shared_isr)(void *arg);
+
+/* Initializes the Shared System Interrupt service */
+extern int BSP_shared_interrupt_init(void);
+
+/* Registers a shared IRQ handler, and enable it at IRQ controller. Multiple
+ * interrupt handlers may use the same IRQ number, all ISRs will be called
+ * when an interrupt on that line is fired.
+ *
+ * Arguments
+ *  irq       System IRQ number
+ *  info      Optional Name of IRQ source
+ *  isr       Function pointer to the ISR
+ *  arg       Second argument to function isr
+ */
+static __inline__ int BSP_shared_interrupt_register
+	(
+	int irq,
+	const char *info,
+	bsp_shared_isr isr,
+	void *arg
+	)
+{
+	return rtems_interrupt_handler_install(irq, info,
+					RTEMS_INTERRUPT_SHARED,	isr, arg);
+}
+
+/* Unregister previously registered shared IRQ handler.
+ *
+ * Arguments
+ *  irq       System IRQ number
+ *  isr       Function pointer to the ISR
+ *  arg       Second argument to function isr
+ */
+static __inline__ int BSP_shared_interrupt_unregister
+	(
+	int irq,
+	bsp_shared_isr isr,
+	void *arg
+	)
+{
+	return rtems_interrupt_handler_remove(irq, isr, arg);
+}
+
+/* Clear interrupt pending on IRQ controller, this is typically done on a 
+ * level triggered interrupt source such as PCI to avoid taking double IRQs.
+ * In such a case the interrupt source must be cleared first on LEON, before 
+ * acknowledging the IRQ with this function.
+ *
+ * Arguments
+ *  irq       System IRQ number
+ */
+extern void BSP_shared_interrupt_clear(int irq);
+
+/* Enable Interrupt. This function will unmask the IRQ at the interrupt
+ * controller. This is normally done by _register(). Note that this will
+ * affect all ISRs on this IRQ.
+ *
+ * Arguments
+ *  irq       System IRQ number
+ */
+extern void BSP_shared_interrupt_unmask(int irq);
+
+/* Disable Interrupt. This function will mask one IRQ at the interrupt
+ * controller. This is normally done by _unregister().  Note that this will
+ * affect all ISRs on this IRQ.
+ *
+ * Arguments
+ *  irq         System IRQ number
+ */
+extern void BSP_shared_interrupt_mask(int irq);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/c/src/lib/libbsp/sparc/erc32/include/bsp/irq.h b/c/src/lib/libbsp/sparc/erc32/include/bsp/irq.h
new file mode 100644
index 0000000..c0e931b
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/erc32/include/bsp/irq.h
@@ -0,0 +1,20 @@
+/* ERC32 generic shared IRQ setup
+ *
+ * Based on libbsp/shared/include/irq.h.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ERC32_IRQ_CONFIG_H
+#define LIBBSP_ERC32_IRQ_CONFIG_H
+
+#define BSP_INTERRUPT_VECTOR_MAX_STD 15 /* Standard IRQ controller */
+#define BSP_INTERRUPT_VECTOR_MIN 0
+#define BSP_INTERRUPT_VECTOR_MAX BSP_INTERRUPT_VECTOR_MAX_STD
+
+/* No extra check is needed */
+#undef BSP_INTERRUPT_CUSTOM_VALID_VECTOR
+
+#endif /* LIBBSP_ERC32_IRQ_CONFIG_H */
diff --git a/c/src/lib/libbsp/sparc/erc32/include/erc32.h b/c/src/lib/libbsp/sparc/erc32/include/erc32.h
index dcc6190..4f4b9b0 100644
--- a/c/src/lib/libbsp/sparc/erc32/include/erc32.h
+++ b/c/src/lib/libbsp/sparc/erc32/include/erc32.h
@@ -324,6 +324,11 @@ typedef struct {
 
 extern ERC32_Register_Map ERC32_MEC;
 
+static __inline__ int bsp_irq_fixup(int irq)
+{
+	return irq;
+}
+
 /*
  *  Macros to manipulate the Interrupt Clear, Interrupt Force, Interrupt Mask,
  *  and the Interrupt Pending Registers.
@@ -396,6 +401,18 @@ extern ERC32_Register_Map ERC32_MEC;
     sparc_enable_interrupts( _level ); \
   } while (0)
 
+/* Make all SPARC BSPs have common macros for interrupt handling */
+#define BSP_Clear_interrupt(_source) ERC32_Clear_interrupt(_source)
+#define BSP_Force_interrupt(_source) ERC32_Force_interrupt(_source)
+#define BSP_Is_interrupt_pending(_source) ERC32_Is_interrupt_pending(_source)
+#define BSP_Is_interrupt_masked(_source) ERC32_Is_interrupt_masked(_source)
+#define BSP_Unmask_interrupt(_source) ERC32_Unmask_interrupt(_source)
+#define BSP_Mask_interrupt(_source) ERC32_Mask_interrupt(_source)
+#define BSP_Disable_interrupt(_source, _previous) \
+        ERC32_Disable_interrupt(_source, _prev)
+#define BSP_Restore_interrupt(_source, _previous) \
+        ERC32_Restore_interrupt(_source, _previous)
+
 /*
  *  The following macros attempt to hide the fact that the General Purpose
  *  Timer and Real Time Clock Timer share the Timer Control Register.  Because
diff --git a/c/src/lib/libbsp/sparc/erc32/preinstall.am b/c/src/lib/libbsp/sparc/erc32/preinstall.am
index 6c0b907..a235296 100644
--- a/c/src/lib/libbsp/sparc/erc32/preinstall.am
+++ b/c/src/lib/libbsp/sparc/erc32/preinstall.am
@@ -73,3 +73,15 @@ $(PROJECT_LIB)/linkcmds.base: ../shared/startup/linkcmds.base $(PROJECT_LIB)/$(d
 	$(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds.base
 PREINSTALL_FILES += $(PROJECT_LIB)/linkcmds.base
 
+$(PROJECT_INCLUDE)/bsp/irq-generic.h: ../../shared/include/irq-generic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-generic.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-generic.h
+
+$(PROJECT_INCLUDE)/bsp/irq-info.h: ../../shared/include/irq-info.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-info.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-info.h
+
+$(PROJECT_INCLUDE)/bsp/irq.h: include/bsp/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h
+
diff --git a/c/src/lib/libbsp/sparc/erc32/startup/bsppredriver.c b/c/src/lib/libbsp/sparc/erc32/startup/bsppredriver.c
new file mode 100644
index 0000000..4084b5c
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/erc32/startup/bsppredriver.c
@@ -0,0 +1,25 @@
+/*  Installs the BSP pre-driver hook
+ *
+ *  COPYRIGHT (c) 2011
+ *  Aeroflex Gaisler
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <bsp.h>
+
+/*
+ *  bsp_predriver_hook
+ *
+ *  BSP predriver hook. Called just before drivers are initialized.
+ *  Is used to initialize shared interrupt handling.
+ */
+void bsp_predriver_hook( void )
+{
+  /* Initialize shared interrupt handling, must be done after IRQ
+   * controller has been found and initialized.
+   */
+  BSP_shared_interrupt_init();
+}
diff --git a/c/src/lib/libbsp/sparc/leon2/Makefile.am b/c/src/lib/libbsp/sparc/leon2/Makefile.am
index 6e2697f..2acca78 100644
--- a/c/src/lib/libbsp/sparc/leon2/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon2/Makefile.am
@@ -51,7 +51,7 @@ libbsp_a_SOURCES =
 
 # startup
 libbsp_a_SOURCES += ../../shared/bspclean.c ../../shared/bsplibc.c \
-    ../../shared/bsppost.c ../../shared/bsppredriverhook.c \
+    ../../shared/bsppost.c startup/bsppredriver.c \
     startup/bspstart.c ../../sparc/shared/bsppretaskinghook.c \
     ../../sparc/shared/bspgetworkarea.c ../../shared/bootcard.c \
     ../../shared/sbrk.c startup/setvec.c startup/spurious.c startup/bspidle.c \
@@ -66,6 +66,19 @@ libbsp_a_SOURCES += console/console.c console/debugputs.c
 # clock
 libbsp_a_SOURCES += clock/ckinit.c
 libbsp_a_SOURCES += ../../shared/clockdrv_shell.h
+# IRQ
+include_bsp_HEADERS = \
+    ../../shared/include/irq-generic.h \
+    ../../shared/include/irq-info.h \
+    include/bsp/irq.h
+libbsp_a_SOURCES += \
+    ../../sparc/shared/irq/irq-shared.c \
+    ../../shared/src/irq-default-handler.c \
+    ../../shared/src/irq-generic.c \
+    ../../shared/src/irq-info.c \
+    ../../shared/src/irq-legacy.c \
+    ../../shared/src/irq-server.c \
+    ../../shared/src/irq-shell.c
 # AMBA PnP Scanning
 libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp.c
 # PCI
diff --git a/c/src/lib/libbsp/sparc/leon2/include/bsp.h b/c/src/lib/libbsp/sparc/leon2/include/bsp.h
index a2f3360..b087e06 100644
--- a/c/src/lib/libbsp/sparc/leon2/include/bsp.h
+++ b/c/src/lib/libbsp/sparc/leon2/include/bsp.h
@@ -30,6 +30,7 @@ extern "C" {
 #include <leon.h>
 #include <rtems/clockdrv.h>
 #include <rtems/console.h>
+#include <rtems/irq-extension.h>
 
 /* SPARC CPU variant: LEON2 */
 #define LEON2 1
@@ -109,6 +110,79 @@ void bsp_spurious_initialize( void );
  */
 void *bsp_early_malloc(int size);
 
+/* Interrupt Service Routine (ISR) pointer */
+typedef void (*bsp_shared_isr)(void *arg);
+
+/* Initializes the Shared System Interrupt service */
+extern int BSP_shared_interrupt_init(void);
+
+/* Registers a shared IRQ handler, and enable it at IRQ controller. Multiple
+ * interrupt handlers may use the same IRQ number, all ISRs will be called
+ * when an interrupt on that line is fired.
+ *
+ * Arguments
+ *  irq       System IRQ number
+ *  info      Optional Name of IRQ source
+ *  isr       Function pointer to the ISR
+ *  arg       Second argument to function isr
+ */
+static __inline__ int BSP_shared_interrupt_register
+	(
+	int irq,
+	const char *info,
+	bsp_shared_isr isr,
+	void *arg
+	)
+{
+	return rtems_interrupt_handler_install(irq, info,
+					RTEMS_INTERRUPT_SHARED,	isr, arg);
+}
+
+/* Unregister previously registered shared IRQ handler.
+ *
+ * Arguments
+ *  irq       System IRQ number
+ *  isr       Function pointer to the ISR
+ *  arg       Second argument to function isr
+ */
+static __inline__ int BSP_shared_interrupt_unregister
+	(
+	int irq,
+	bsp_shared_isr isr,
+	void *arg
+	)
+{
+	return rtems_interrupt_handler_remove(irq, isr, arg);
+}
+
+/* Clear interrupt pending on IRQ controller, this is typically done on a 
+ * level triggered interrupt source such as PCI to avoid taking double IRQs.
+ * In such a case the interrupt source must be cleared first on LEON, before 
+ * acknowledging the IRQ with this function.
+ *
+ * Arguments
+ *  irq       System IRQ number
+ */
+extern void BSP_shared_interrupt_clear(int irq);
+
+/* Enable Interrupt. This function will unmask the IRQ at the interrupt
+ * controller. This is normally done by _register(). Note that this will
+ * affect all ISRs on this IRQ.
+ *
+ * Arguments
+ *  irq       System IRQ number
+ */
+extern void BSP_shared_interrupt_unmask(int irq);
+
+/* Disable Interrupt. This function will mask one IRQ at the interrupt
+ * controller. This is normally done by _unregister().  Note that this will
+ * affect all ISRs on this IRQ.
+ *
+ * Arguments
+ *  irq         System IRQ number
+ */
+extern void BSP_shared_interrupt_mask(int irq);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/c/src/lib/libbsp/sparc/leon2/include/bsp/irq.h b/c/src/lib/libbsp/sparc/leon2/include/bsp/irq.h
new file mode 100644
index 0000000..709b563
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/leon2/include/bsp/irq.h
@@ -0,0 +1,20 @@
+/* LEON2 generic shared IRQ setup
+ *
+ * Based on libbsp/shared/include/irq.h.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_LEON2_IRQ_CONFIG_H
+#define LIBBSP_LEON2_IRQ_CONFIG_H
+
+#define BSP_INTERRUPT_VECTOR_MAX_STD 15 /* Standard IRQ controller */
+#define BSP_INTERRUPT_VECTOR_MIN 0
+#define BSP_INTERRUPT_VECTOR_MAX BSP_INTERRUPT_VECTOR_MAX_STD
+
+/* No extra check is needed */
+#undef BSP_INTERRUPT_CUSTOM_VALID_VECTOR
+
+#endif /* LIBBSP_LEON2_IRQ_CONFIG_H */
diff --git a/c/src/lib/libbsp/sparc/leon2/include/leon.h b/c/src/lib/libbsp/sparc/leon2/include/leon.h
index c183c90..726a5a7 100644
--- a/c/src/lib/libbsp/sparc/leon2/include/leon.h
+++ b/c/src/lib/libbsp/sparc/leon2/include/leon.h
@@ -271,6 +271,11 @@ typedef struct {
 
 extern LEON_Register_Map LEON_REG;
 
+static __inline__ int bsp_irq_fixup(int irq)
+{
+	return irq;
+}
+
 /*
  *  Macros to manipulate the Interrupt Clear, Interrupt Force, Interrupt Mask,
  *  and the Interrupt Pending Registers.
@@ -338,6 +343,18 @@ extern LEON_Register_Map LEON_REG;
     sparc_enable_interrupts( _level ); \
   } while (0)
 
+/* Make all SPARC BSPs have common macros for interrupt handling */
+#define BSP_Clear_interrupt(_source) LEON_Clear_interrupt(_source)
+#define BSP_Force_interrupt(_source) LEON_Force_interrupt(_source)
+#define BSP_Is_interrupt_pending(_source) LEON_Is_interrupt_pending(_source)
+#define BSP_Is_interrupt_masked(_source) LEON_Is_interrupt_masked(_source)
+#define BSP_Unmask_interrupt(_source) LEON_Unmask_interrupt(_source)
+#define BSP_Mask_interrupt(_source) LEON_Mask_interrupt(_source)
+#define BSP_Disable_interrupt(_source, _previous) \
+        LEON_Disable_interrupt(_source, _prev)
+#define BSP_Restore_interrupt(_source, _previous) \
+        LEON_Restore_interrupt(_source, _previous)
+
 /*
  *  Each timer control register is organized as follows:
  *
diff --git a/c/src/lib/libbsp/sparc/leon2/preinstall.am b/c/src/lib/libbsp/sparc/leon2/preinstall.am
index 4b7d4da..00ed05e 100644
--- a/c/src/lib/libbsp/sparc/leon2/preinstall.am
+++ b/c/src/lib/libbsp/sparc/leon2/preinstall.am
@@ -145,6 +145,18 @@ $(PROJECT_LIB)/linkcmds.base: ../shared/startup/linkcmds.base $(PROJECT_LIB)/$(d
 	$(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds.base
 PREINSTALL_FILES += $(PROJECT_LIB)/linkcmds.base
 
+$(PROJECT_INCLUDE)/bsp/irq-generic.h: ../../shared/include/irq-generic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-generic.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-generic.h
+
+$(PROJECT_INCLUDE)/bsp/irq-info.h: ../../shared/include/irq-info.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-info.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-info.h
+
+$(PROJECT_INCLUDE)/bsp/irq.h: include/bsp/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h
+
 $(PROJECT_INCLUDE)/i2cmst.h: ../../sparc/shared/include/i2cmst.h $(PROJECT_INCLUDE)/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/i2cmst.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/i2cmst.h
diff --git a/c/src/lib/libbsp/sparc/leon2/startup/bsppredriver.c b/c/src/lib/libbsp/sparc/leon2/startup/bsppredriver.c
new file mode 100644
index 0000000..4084b5c
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/leon2/startup/bsppredriver.c
@@ -0,0 +1,25 @@
+/*  Installs the BSP pre-driver hook
+ *
+ *  COPYRIGHT (c) 2011
+ *  Aeroflex Gaisler
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <bsp.h>
+
+/*
+ *  bsp_predriver_hook
+ *
+ *  BSP predriver hook. Called just before drivers are initialized.
+ *  Is used to initialize shared interrupt handling.
+ */
+void bsp_predriver_hook( void )
+{
+  /* Initialize shared interrupt handling, must be done after IRQ
+   * controller has been found and initialized.
+   */
+  BSP_shared_interrupt_init();
+}
diff --git a/c/src/lib/libbsp/sparc/leon3/Makefile.am b/c/src/lib/libbsp/sparc/leon3/Makefile.am
index dc24051..ebbeb46 100644
--- a/c/src/lib/libbsp/sparc/leon3/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon3/Makefile.am
@@ -35,7 +35,7 @@ libbsp_a_SOURCES =
 # startup
 libbsp_a_SOURCES += ../../shared/bspclean.c ../../shared/bsplibc.c \
     ../../shared/bsppost.c ../../shared/bootcard.c startup/bspstart.c \
-    ../../sparc/shared/bsppretaskinghook.c ../../shared/bsppredriverhook.c \
+    ../../sparc/shared/bsppretaskinghook.c startup/bsppredriver.c \
     ../../sparc/shared/bspgetworkarea.c ../../shared/sbrk.c startup/setvec.c \
     startup/spurious.c startup/bspidle.S startup/bspdelay.c \
     ../../shared/bspinit.c ../../sparc/shared/startup/early_malloc.c
@@ -55,6 +55,20 @@ libbsp_a_SOURCES += console/debugputs.c
 # clock
 libbsp_a_SOURCES += clock/ckinit.c
 libbsp_a_SOURCES += ../../shared/clockdrv_shell.h
+# IRQ
+include_bsp_HEADERS = \
+    ../../shared/include/irq-generic.h \
+    ../../shared/include/irq-info.h \
+    include/bsp/irq.h
+libbsp_a_SOURCES += \
+    startup/eirq.c \
+    ../../sparc/shared/irq/irq-shared.c \
+    ../../shared/src/irq-default-handler.c \
+    ../../shared/src/irq-generic.c \
+    ../../shared/src/irq-info.c \
+    ../../shared/src/irq-legacy.c \
+    ../../shared/src/irq-server.c \
+    ../../shared/src/irq-shell.c
 # PCI
 include_HEADERS += ../../sparc/shared/include/pci.h
 libbsp_a_SOURCES += pci/pci.c ../../sparc/shared/pci/pcifinddevice.c
diff --git a/c/src/lib/libbsp/sparc/leon3/amba/amba.c b/c/src/lib/libbsp/sparc/leon3/amba/amba.c
index b0a43f9..03af226 100644
--- a/c/src/lib/libbsp/sparc/leon3/amba/amba.c
+++ b/c/src/lib/libbsp/sparc/leon3/amba/amba.c
@@ -18,6 +18,9 @@
 /* Structure containing address to devices found on the Amba Plug&Play bus */
 amba_confarea_type amba_conf;
 
+/* GRLIB extended IRQ controller register */
+extern void leon3_ext_irq_init(void);
+
 /* Pointers to Interrupt Controller configuration registers */
 volatile LEON3_IrqCtrl_Regs_Map *LEON3_IrqCtrl_Regs;
 
@@ -48,6 +51,9 @@ void amba_initialize(void)
     LEON3_IrqCtrl_Regs = (volatile LEON3_IrqCtrl_Regs_Map *) dev.start;
   }
 
+  /* Init Extended IRQ controller if available */
+  leon3_ext_irq_init();
+
   /* find GP Timer */
   i = amba_find_apbslv(&amba_conf,VENDOR_GAISLER,GAISLER_GPTIMER,&dev);
   if ( i > 0 ){
diff --git a/c/src/lib/libbsp/sparc/leon3/include/bsp.h b/c/src/lib/libbsp/sparc/leon3/include/bsp.h
index 04279d9..fc42773 100644
--- a/c/src/lib/libbsp/sparc/leon3/include/bsp.h
+++ b/c/src/lib/libbsp/sparc/leon3/include/bsp.h
@@ -30,6 +30,7 @@ extern "C" {
 #include <leon.h>
 #include <rtems/clockdrv.h>
 #include <rtems/console.h>
+#include <rtems/irq-extension.h>
 
 /* SPARC CPU variant: LEON3 */
 #define LEON3 1
@@ -119,6 +120,79 @@ void bsp_spurious_initialize( void );
  */
 void *bsp_early_malloc(int size);
 
+/* Interrupt Service Routine (ISR) pointer */
+typedef void (*bsp_shared_isr)(void *arg);
+
+/* Initializes the Shared System Interrupt service */
+extern int BSP_shared_interrupt_init(void);
+
+/* Registers a shared IRQ handler, and enable it at IRQ controller. Multiple
+ * interrupt handlers may use the same IRQ number, all ISRs will be called
+ * when an interrupt on that line is fired.
+ *
+ * Arguments
+ *  irq       System IRQ number
+ *  info      Optional Name of IRQ source
+ *  isr       Function pointer to the ISR
+ *  arg       Second argument to function isr
+ */
+static __inline__ int BSP_shared_interrupt_register
+	(
+	int irq,
+	const char *info,
+	bsp_shared_isr isr,
+	void *arg
+	)
+{
+	return rtems_interrupt_handler_install(irq, info,
+					RTEMS_INTERRUPT_SHARED,	isr, arg);
+}
+
+/* Unregister previously registered shared IRQ handler.
+ *
+ * Arguments
+ *  irq       System IRQ number
+ *  isr       Function pointer to the ISR
+ *  arg       Second argument to function isr
+ */
+static __inline__ int BSP_shared_interrupt_unregister
+	(
+	int irq,
+	bsp_shared_isr isr,
+	void *arg
+	)
+{
+	return rtems_interrupt_handler_remove(irq, isr, arg);
+}
+
+/* Clear interrupt pending on IRQ controller, this is typically done on a 
+ * level triggered interrupt source such as PCI to avoid taking double IRQs.
+ * In such a case the interrupt source must be cleared first on LEON, before 
+ * acknowledging the IRQ with this function.
+ *
+ * Arguments
+ *  irq       System IRQ number
+ */
+extern void BSP_shared_interrupt_clear(int irq);
+
+/* Enable Interrupt. This function will unmask the IRQ at the interrupt
+ * controller. This is normally done by _register(). Note that this will
+ * affect all ISRs on this IRQ.
+ *
+ * Arguments
+ *  irq       System IRQ number
+ */
+extern void BSP_shared_interrupt_unmask(int irq);
+
+/* Disable Interrupt. This function will mask one IRQ at the interrupt
+ * controller. This is normally done by _unregister().  Note that this will
+ * affect all ISRs on this IRQ.
+ *
+ * Arguments
+ *  irq         System IRQ number
+ */
+extern void BSP_shared_interrupt_mask(int irq);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/c/src/lib/libbsp/sparc/leon3/include/bsp/irq.h b/c/src/lib/libbsp/sparc/leon3/include/bsp/irq.h
new file mode 100644
index 0000000..71c0df3
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/leon3/include/bsp/irq.h
@@ -0,0 +1,36 @@
+/* LEON3 generic shared IRQ setup
+ *
+ * Based on libbsp/shared/include/irq.h.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_LEON3_IRQ_CONFIG_H
+#define LIBBSP_LEON3_IRQ_CONFIG_H
+
+#define BSP_INTERRUPT_VECTOR_MAX_STD 15 /* Standard IRQ controller */
+#define BSP_INTERRUPT_VECTOR_MAX_EXT 31 /* Extended IRQ controller */
+
+#define BSP_INTERRUPT_VECTOR_MIN 0
+#define BSP_INTERRUPT_VECTOR_MAX BSP_INTERRUPT_VECTOR_MAX_EXT
+
+/* The check is different depending on IRQ controller, runtime detected */
+#define BSP_INTERRUPT_CUSTOM_VALID_VECTOR
+
+extern int LEON3_IrqCtrl_EIrq;
+
+/**
+ * @brief Returns true if the interrupt vector with number @a vector is valid.
+ */
+static inline bool bsp_interrupt_is_valid_vector(rtems_vector_number vector)
+{
+  return (rtems_vector_number) BSP_INTERRUPT_VECTOR_MIN <= vector
+    && ((vector <= (rtems_vector_number) BSP_INTERRUPT_VECTOR_MAX_STD &&
+        LEON3_IrqCtrl_EIrq == 0) ||
+       (vector <= (rtems_vector_number) BSP_INTERRUPT_VECTOR_MAX_EXT &&
+        LEON3_IrqCtrl_EIrq != 0));
+}
+
+#endif /* LIBBSP_LEON3_IRQ_CONFIG_H */
diff --git a/c/src/lib/libbsp/sparc/leon3/include/leon.h b/c/src/lib/libbsp/sparc/leon3/include/leon.h
index fd208b0..40617b1 100644
--- a/c/src/lib/libbsp/sparc/leon3/include/leon.h
+++ b/c/src/lib/libbsp/sparc/leon3/include/leon.h
@@ -152,6 +152,23 @@ extern volatile LEON3_UART_Regs_Map *LEON3_Console_Uart[LEON3_APBUARTS];
 /* LEON3 CPU Index of boot CPU */
 extern int LEON3_Cpu_Index;
 
+/* The external IRQ number, -1 if not external interrupts */
+extern int LEON3_IrqCtrl_EIrq;
+
+static __inline__ int bsp_irq_fixup(int irq)
+{
+	int eirq;
+
+	if (LEON3_IrqCtrl_EIrq != 0 && irq == LEON3_IrqCtrl_EIrq) {
+		/* Get interrupt number from IRQ controller */
+		eirq = LEON3_IrqCtrl_Regs->intid[LEON3_Cpu_Index] & 0x1f;
+		if (eirq & 0x10)
+			irq = eirq;
+	}
+
+	return irq;
+}
+
 /* Macros used for manipulating bits in LEON3 GP Timer Control Register */
 
 #define LEON3_GPTIMER_EN 1
@@ -232,6 +249,17 @@ extern int LEON3_Cpu_Index;
     sparc_enable_interrupts( _level ); \
   } while (0)
 
+/* Make all SPARC BSPs have common macros for interrupt handling */
+#define BSP_Clear_interrupt(_source) LEON_Clear_interrupt(_source)
+#define BSP_Force_interrupt(_source) LEON_Force_interrupt(_source)
+#define BSP_Is_interrupt_pending(_source) LEON_Is_interrupt_pending(_source)
+#define BSP_Is_interrupt_masked(_source) LEON_Is_interrupt_masked(_source)
+#define BSP_Unmask_interrupt(_source) LEON_Unmask_interrupt(_source)
+#define BSP_Mask_interrupt(_source) LEON_Mask_interrupt(_source)
+#define BSP_Disable_interrupt(_source, _previous) \
+        LEON_Disable_interrupt(_source, _prev)
+#define BSP_Restore_interrupt(_source, _previous) \
+        LEON_Restore_interrupt(_source, _previous)
 
 /*
  *  Each timer control register is organized as follows:
diff --git a/c/src/lib/libbsp/sparc/leon3/preinstall.am b/c/src/lib/libbsp/sparc/leon3/preinstall.am
index b948529..8c27b81 100644
--- a/c/src/lib/libbsp/sparc/leon3/preinstall.am
+++ b/c/src/lib/libbsp/sparc/leon3/preinstall.am
@@ -85,6 +85,18 @@ $(PROJECT_INCLUDE)/ambapp.h: ../../sparc/shared/include/ambapp.h $(PROJECT_INCLU
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/ambapp.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/ambapp.h
 
+$(PROJECT_INCLUDE)/bsp/irq-generic.h: ../../shared/include/irq-generic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-generic.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-generic.h
+
+$(PROJECT_INCLUDE)/bsp/irq-info.h: ../../shared/include/irq-info.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-info.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-info.h
+
+$(PROJECT_INCLUDE)/bsp/irq.h: include/bsp/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h
+
 $(PROJECT_INCLUDE)/pci.h: ../../sparc/shared/include/pci.h $(PROJECT_INCLUDE)/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pci.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci.h
diff --git a/c/src/lib/libbsp/sparc/leon3/startup/bsppredriver.c b/c/src/lib/libbsp/sparc/leon3/startup/bsppredriver.c
new file mode 100644
index 0000000..4084b5c
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/leon3/startup/bsppredriver.c
@@ -0,0 +1,25 @@
+/*  Installs the BSP pre-driver hook
+ *
+ *  COPYRIGHT (c) 2011
+ *  Aeroflex Gaisler
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <bsp.h>
+
+/*
+ *  bsp_predriver_hook
+ *
+ *  BSP predriver hook. Called just before drivers are initialized.
+ *  Is used to initialize shared interrupt handling.
+ */
+void bsp_predriver_hook( void )
+{
+  /* Initialize shared interrupt handling, must be done after IRQ
+   * controller has been found and initialized.
+   */
+  BSP_shared_interrupt_init();
+}
diff --git a/c/src/lib/libbsp/sparc/leon3/startup/eirq.c b/c/src/lib/libbsp/sparc/leon3/startup/eirq.c
new file mode 100644
index 0000000..d62035e
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/leon3/startup/eirq.c
@@ -0,0 +1,25 @@
+/*
+ *  GRLIB/LEON3 extended interrupt controller
+ *
+ *  COPYRIGHT (c) 2011
+ *  Aeroflex Gaisler
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+#include <bsp.h>
+
+/* GRLIB extended IRQ controller IRQ number */
+int LEON3_IrqCtrl_EIrq = -1;
+
+/* Initialize Extended Interrupt controller */
+void leon3_ext_irq_init(void)
+{
+  if ( (LEON3_IrqCtrl_Regs->mpstat >> 16) & 0xf ) {
+    /* Extended IRQ controller available */
+    LEON3_IrqCtrl_EIrq = (LEON3_IrqCtrl_Regs->mpstat >> 16) & 0xf;
+  }
+}
diff --git a/c/src/lib/libbsp/sparc/shared/include/ambapp.h b/c/src/lib/libbsp/sparc/shared/include/ambapp.h
index e2b557d..cc8e120 100644
--- a/c/src/lib/libbsp/sparc/shared/include/ambapp.h
+++ b/c/src/lib/libbsp/sparc/shared/include/ambapp.h
@@ -272,6 +272,8 @@ typedef struct {
   volatile unsigned int notused23;
   volatile unsigned int mask[16];
   volatile unsigned int force[16];
+  /* Extended IRQ registers */
+  volatile unsigned int intid[16];
 } LEON3_IrqCtrl_Regs_Map;
 
 /*****************************/
diff --git a/c/src/lib/libbsp/sparc/shared/irq/irq-shared.c b/c/src/lib/libbsp/sparc/shared/irq/irq-shared.c
new file mode 100644
index 0000000..5f478ef
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/shared/irq/irq-shared.c
@@ -0,0 +1,83 @@
+#include <rtems.h>
+#include <bsp.h>
+#include <bsp/irq-generic.h>
+
+static inline void bsp_dispatch_irq(int irq)
+{
+	bsp_interrupt_handler_entry *e =
+		&bsp_interrupt_handler_table[bsp_interrupt_handler_index(irq)];
+
+	while (e != NULL) {
+		(*e->handler)(e->arg);
+		e = e->next;
+	}
+}
+
+/* Called directly from IRQ trap handler TRAP[0x10..0x1F] = IRQ[0..15] */
+static void BSP_ISR_handler(rtems_vector_number vector)
+{
+	int irq = vector - 0x10;
+
+	/* Let BSP fixup and/or handle incomming IRQ */
+	irq = bsp_irq_fixup(irq);
+
+	bsp_dispatch_irq(irq);
+}
+
+/* Initialize interrupts */
+int BSP_shared_interrupt_init(void)
+{
+	rtems_vector_number vector;
+	rtems_isr_entry previous_isr;
+	int sc, i;
+
+	for (i=0; i <= BSP_INTERRUPT_VECTOR_MAX_STD; i++) {
+		vector = SPARC_ASYNCHRONOUS_TRAP(i) + 0x10;
+		rtems_interrupt_catch(BSP_ISR_handler, vector, &previous_isr);
+	}
+
+	/* Initalize interrupt support */
+	sc = bsp_interrupt_initialize();
+	if (sc != RTEMS_SUCCESSFUL)
+		return -1;
+
+	return 0;
+}
+
+/* Callback from bsp_interrupt_initialize() */
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+	return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+	BSP_Unmask_interrupt((int)vector);
+
+	return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+	BSP_Mask_interrupt((int)vector);
+
+	return RTEMS_SUCCESSFUL;
+}
+
+void BSP_shared_interrupt_mask(int irq)
+{
+	BSP_Mask_interrupt(irq);
+}
+
+void BSP_shared_interrupt_unmask(int irq)
+{
+	BSP_Unmask_interrupt(irq);
+}
+
+void BSP_shared_interrupt_clear(int irq)
+{
+	/* We don't have to interrupt lock here, because the register is only
+	 * written and self clearing
+	 */
+	BSP_Clear_interrupt(irq);
+}
-- 
1.7.0.4




More information about the devel mailing list