diff options
23 files changed, 634 insertions, 4 deletions
diff --git a/c/src/lib/libbsp/sparc/Makefile.am b/c/src/lib/libbsp/sparc/Makefile.am index b1b6a22869..4f445ba49d 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 e70310df54..615a3e098a 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 a88673ebf4..879e7144e0 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 @@ -86,6 +86,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 0000000000..c0e931b1b2 --- /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 dcc619069f..2795dcb13b 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 6c0b907910..a235296e1f 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 0000000000..4084b5ca97 --- /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 6e2697fb15..2acca78685 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 796290e915..e96a63ee90 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 @@ -105,6 +106,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 0000000000..709b5631aa --- /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 c183c90ff4..1e4bff2cb5 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 4b7d4daf29..00ed05ea78 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 0000000000..4084b5ca97 --- /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 dc24051b64..ebbeb46b18 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 b0a43f9c19..03af2265d2 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 07a7412e16..e5ae2c1912 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 @@ -115,6 +116,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 0000000000..71c0df3c5d --- /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 fd208b083a..819800cf59 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 b948529704..8c27b81933 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 0000000000..4084b5ca97 --- /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 0000000000..d62035ec84 --- /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 e2b557d85e..cc8e12005a 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 0000000000..22f2564723 --- /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); +} |