SPARC BSPs: implemented shared-irq using libbsp/shared layer

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@gaisler.com>

Regenerate
This commit is contained in:
Daniel Hellstrom
2012-04-06 05:05:07 -05:00
committed by Joel Sherrill
parent e60e862c64
commit 95518e59bd
23 changed files with 634 additions and 4 deletions

View File

@@ -12,6 +12,9 @@ EXTRA_DIST =
EXTRA_DIST += shared/gnatcommon.c EXTRA_DIST += shared/gnatcommon.c
EXTRA_DIST += shared/start.S EXTRA_DIST += shared/start.S
# Interrupt
EXTRA_DIST += shared/irq/irq-shared.c
# AMBA Plug&Play bus # AMBA Plug&Play bus
EXTRA_DIST += shared/include/ambapp.h EXTRA_DIST += shared/include/ambapp.h
EXTRA_DIST += shared/amba/ambapp.c EXTRA_DIST += shared/amba/ambapp.c

View File

@@ -33,7 +33,7 @@ libbsp_a_SOURCES =
# startup # startup
libbsp_a_SOURCES += ../../shared/bspclean.c ../../shared/bsplibc.c \ 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 \ ../../sparc/shared/bsppretaskinghook.c ../../shared/bsppost.c \
../../shared/bspstart.c ../../shared/bootcard.c ../../shared/bspinit.c \ ../../shared/bspstart.c ../../shared/bootcard.c ../../shared/bspinit.c \
../../shared/sbrk.c startup/setvec.c startup/spurious.c \ ../../shared/sbrk.c startup/setvec.c startup/spurious.c \
@@ -55,6 +55,20 @@ libbsp_a_SOURCES += ../../shared/clockdrv_shell.h
# timer # timer
libbsp_a_SOURCES += timer/timer.c 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 if HAS_SMP
libbsp_a_SOURCES += ../../shared/smp/getcpuid.c ../../shared/smp/smp_stub.c \ libbsp_a_SOURCES += ../../shared/smp/getcpuid.c ../../shared/smp/smp_stub.c \
../../shared/smp/bspsmp_wait_for.c ../../shared/smp/bspsmp_wait_for.c

View File

@@ -30,8 +30,8 @@ extern "C" {
#include <rtems/iosupp.h> #include <rtems/iosupp.h>
#include <erc32.h> #include <erc32.h>
#include <rtems/clockdrv.h> #include <rtems/clockdrv.h>
#include <rtems/console.h> #include <rtems/console.h>
#include <rtems/irq-extension.h>
/* /*
* BSP provides its own Idle thread body * BSP provides its own Idle thread body
@@ -86,6 +86,79 @@ void bsp_spurious_initialize( void );
*/ */
void *bsp_early_malloc(int size); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@@ -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 */

View File

@@ -324,6 +324,11 @@ typedef struct {
extern ERC32_Register_Map ERC32_MEC; 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, * Macros to manipulate the Interrupt Clear, Interrupt Force, Interrupt Mask,
* and the Interrupt Pending Registers. * and the Interrupt Pending Registers.
@@ -396,6 +401,18 @@ extern ERC32_Register_Map ERC32_MEC;
sparc_enable_interrupts( _level ); \ sparc_enable_interrupts( _level ); \
} while (0) } 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 * The following macros attempt to hide the fact that the General Purpose
* Timer and Real Time Clock Timer share the Timer Control Register. Because * Timer and Real Time Clock Timer share the Timer Control Register. Because

View File

@@ -73,3 +73,15 @@ $(PROJECT_LIB)/linkcmds.base: ../shared/startup/linkcmds.base $(PROJECT_LIB)/$(d
$(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds.base $(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds.base
PREINSTALL_FILES += $(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

View File

@@ -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();
}

View File

@@ -51,7 +51,7 @@ libbsp_a_SOURCES =
# startup # startup
libbsp_a_SOURCES += ../../shared/bspclean.c ../../shared/bsplibc.c \ 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 \ startup/bspstart.c ../../sparc/shared/bsppretaskinghook.c \
../../sparc/shared/bspgetworkarea.c ../../shared/bootcard.c \ ../../sparc/shared/bspgetworkarea.c ../../shared/bootcard.c \
../../shared/sbrk.c startup/setvec.c startup/spurious.c startup/bspidle.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 # clock
libbsp_a_SOURCES += clock/ckinit.c libbsp_a_SOURCES += clock/ckinit.c
libbsp_a_SOURCES += ../../shared/clockdrv_shell.h 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 # AMBA PnP Scanning
libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp.c libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp.c
# PCI # PCI

View File

@@ -30,6 +30,7 @@ extern "C" {
#include <leon.h> #include <leon.h>
#include <rtems/clockdrv.h> #include <rtems/clockdrv.h>
#include <rtems/console.h> #include <rtems/console.h>
#include <rtems/irq-extension.h>
/* SPARC CPU variant: LEON2 */ /* SPARC CPU variant: LEON2 */
#define LEON2 1 #define LEON2 1
@@ -105,6 +106,79 @@ void bsp_spurious_initialize( void );
*/ */
void *bsp_early_malloc(int size); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@@ -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 */

View File

@@ -271,6 +271,11 @@ typedef struct {
extern LEON_Register_Map LEON_REG; 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, * Macros to manipulate the Interrupt Clear, Interrupt Force, Interrupt Mask,
* and the Interrupt Pending Registers. * and the Interrupt Pending Registers.
@@ -338,6 +343,18 @@ extern LEON_Register_Map LEON_REG;
sparc_enable_interrupts( _level ); \ sparc_enable_interrupts( _level ); \
} while (0) } 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: * Each timer control register is organized as follows:
* *

View File

@@ -145,6 +145,18 @@ $(PROJECT_LIB)/linkcmds.base: ../shared/startup/linkcmds.base $(PROJECT_LIB)/$(d
$(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds.base $(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds.base
PREINSTALL_FILES += $(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) $(PROJECT_INCLUDE)/i2cmst.h: ../../sparc/shared/include/i2cmst.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/i2cmst.h $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/i2cmst.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/i2cmst.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/i2cmst.h

View File

@@ -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();
}

View File

@@ -35,7 +35,7 @@ libbsp_a_SOURCES =
# startup # startup
libbsp_a_SOURCES += ../../shared/bspclean.c ../../shared/bsplibc.c \ libbsp_a_SOURCES += ../../shared/bspclean.c ../../shared/bsplibc.c \
../../shared/bsppost.c ../../shared/bootcard.c startup/bspstart.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 \ ../../sparc/shared/bspgetworkarea.c ../../shared/sbrk.c startup/setvec.c \
startup/spurious.c startup/bspidle.S startup/bspdelay.c \ startup/spurious.c startup/bspidle.S startup/bspdelay.c \
../../shared/bspinit.c ../../sparc/shared/startup/early_malloc.c ../../shared/bspinit.c ../../sparc/shared/startup/early_malloc.c
@@ -55,6 +55,20 @@ libbsp_a_SOURCES += console/debugputs.c
# clock # clock
libbsp_a_SOURCES += clock/ckinit.c libbsp_a_SOURCES += clock/ckinit.c
libbsp_a_SOURCES += ../../shared/clockdrv_shell.h 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 # PCI
include_HEADERS += ../../sparc/shared/include/pci.h include_HEADERS += ../../sparc/shared/include/pci.h
libbsp_a_SOURCES += pci/pci.c ../../sparc/shared/pci/pcifinddevice.c libbsp_a_SOURCES += pci/pci.c ../../sparc/shared/pci/pcifinddevice.c

View File

@@ -18,6 +18,9 @@
/* Structure containing address to devices found on the Amba Plug&Play bus */ /* Structure containing address to devices found on the Amba Plug&Play bus */
amba_confarea_type amba_conf; amba_confarea_type amba_conf;
/* GRLIB extended IRQ controller register */
extern void leon3_ext_irq_init(void);
/* Pointers to Interrupt Controller configuration registers */ /* Pointers to Interrupt Controller configuration registers */
volatile LEON3_IrqCtrl_Regs_Map *LEON3_IrqCtrl_Regs; 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; LEON3_IrqCtrl_Regs = (volatile LEON3_IrqCtrl_Regs_Map *) dev.start;
} }
/* Init Extended IRQ controller if available */
leon3_ext_irq_init();
/* find GP Timer */ /* find GP Timer */
i = amba_find_apbslv(&amba_conf,VENDOR_GAISLER,GAISLER_GPTIMER,&dev); i = amba_find_apbslv(&amba_conf,VENDOR_GAISLER,GAISLER_GPTIMER,&dev);
if ( i > 0 ){ if ( i > 0 ){

View File

@@ -30,6 +30,7 @@ extern "C" {
#include <leon.h> #include <leon.h>
#include <rtems/clockdrv.h> #include <rtems/clockdrv.h>
#include <rtems/console.h> #include <rtems/console.h>
#include <rtems/irq-extension.h>
/* SPARC CPU variant: LEON3 */ /* SPARC CPU variant: LEON3 */
#define LEON3 1 #define LEON3 1
@@ -115,6 +116,79 @@ void bsp_spurious_initialize( void );
*/ */
void *bsp_early_malloc(int size); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@@ -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 */

View File

@@ -152,6 +152,23 @@ extern volatile LEON3_UART_Regs_Map *LEON3_Console_Uart[LEON3_APBUARTS];
/* LEON3 CPU Index of boot CPU */ /* LEON3 CPU Index of boot CPU */
extern int LEON3_Cpu_Index; 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 */ /* Macros used for manipulating bits in LEON3 GP Timer Control Register */
#define LEON3_GPTIMER_EN 1 #define LEON3_GPTIMER_EN 1
@@ -232,6 +249,17 @@ extern int LEON3_Cpu_Index;
sparc_enable_interrupts( _level ); \ sparc_enable_interrupts( _level ); \
} while (0) } 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: * Each timer control register is organized as follows:

View File

@@ -85,6 +85,18 @@ $(PROJECT_INCLUDE)/ambapp.h: ../../sparc/shared/include/ambapp.h $(PROJECT_INCLU
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/ambapp.h $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/ambapp.h
PREINSTALL_FILES += $(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) $(PROJECT_INCLUDE)/pci.h: ../../sparc/shared/include/pci.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pci.h $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pci.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci.h

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -272,6 +272,8 @@ typedef struct {
volatile unsigned int notused23; volatile unsigned int notused23;
volatile unsigned int mask[16]; volatile unsigned int mask[16];
volatile unsigned int force[16]; volatile unsigned int force[16];
/* Extended IRQ registers */
volatile unsigned int intid[16];
} LEON3_IrqCtrl_Regs_Map; } LEON3_IrqCtrl_Regs_Map;
/*****************************/ /*****************************/

View File

@@ -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);
}