mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-02-11 16:02:34 +00:00
bsps/m68k: Implement new IRQ system
Implements the required bsp directives for the 'new' style rtems
interrupt system. Previously, uC5282 only supported interrupts through
the BSP_installVME_isr directive.
BSP_installVME_isr still behaves the same, but is instead implemented
using the new IRQ directives. To ensure compatibility with existing
EPICS related code without causing subtle bugs, BSP_installVME_isr will
also poke at the EPORT interrupt settings to enable IRQ1 when installing
a "fake VME" interrupt (vector >= 192).
This also fixes a regression from e9cb088995 that broke clock interrupt
handlers, leading to the BSP crashing shortly after boot.
This commit is contained in:
@@ -1 +1,40 @@
|
||||
#include <bsp/irq-default.h>
|
||||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup RTEMSBSPsm68kuC5282
|
||||
*
|
||||
* @brief Core IRQ definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2025 Jeremy Lorelli <lorelli@slac.stanford.edu>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef LIBBSP_M68K_UC5282_IRQ_H
|
||||
#define LIBBSP_M68K_UC5282_IRQ_H
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/irq.h>
|
||||
#include <rtems/irq-extension.h>
|
||||
|
||||
#define BSP_INTERRUPT_CUSTOM_VALID_VECTOR
|
||||
|
||||
#define BSP_INTERRUPT_VECTOR_COUNT 192
|
||||
|
||||
#define BSP_VME_INTERRUPT_VECTOR_COUNT (255 - BSP_INTERRUPT_VECTOR_COUNT)
|
||||
|
||||
#define BSP_FIRST_VME_INTERRUPT_VECTOR BSP_INTERRUPT_VECTOR_COUNT
|
||||
|
||||
extern void uC5282_interrupt_vector_install(rtems_vector_number vector);
|
||||
extern void uC5282_interrupt_vector_remove(rtems_vector_number vector);
|
||||
|
||||
#define bsp_interrupt_vector_install(v) uC5282_interrupt_vector_install(v)
|
||||
#define bsp_interrupt_vector_remove(v) uC5282_interrupt_vector_remove(v)
|
||||
|
||||
#endif // LIBBSP_M68K_UC5282_IRQ_H
|
||||
|
||||
456
bsps/m68k/uC5282/irq/irq.c
Normal file
456
bsps/m68k/uC5282/irq/irq.c
Normal file
@@ -0,0 +1,456 @@
|
||||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2025 Jeremy Lorelli <lorelli@slac.stanford.edu>
|
||||
* Copyright (c) 2005 Eric Norum <eric@norum.ca>
|
||||
* COPYRIGHT (c) 2005.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
#include <bsp.h>
|
||||
#include <bsp/irq.h>
|
||||
#include <mcf5282/mcf5282.h>
|
||||
|
||||
#include <bsp/irq-generic.h>
|
||||
|
||||
typedef void(*void_func_t)(void);
|
||||
|
||||
extern void bsp_default_isr_handler(int);
|
||||
|
||||
/*
|
||||
* Adjust interrupt vector to an offset in INTCn register
|
||||
* MCF5282 interrupt vector mapping:
|
||||
* * 0-63 -- internal CF interrupts
|
||||
* * 64-127 -- INTC0
|
||||
* * 128-191 -- INTC1
|
||||
* * 192-255 -- Unused by hardware; used for fake interrupts in software
|
||||
*/
|
||||
static int vector_to_offset(int vector)
|
||||
{
|
||||
if (vector < 128 && vector >= 64)
|
||||
return vector - 64;
|
||||
else if (vector < 192)
|
||||
return vector - 128;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the associated INTCn chip.
|
||||
* 0 == INTC0, 1 == INTC1, -1 == neither
|
||||
*/
|
||||
static int vector_to_source(int vector)
|
||||
{
|
||||
if (vector < 128 && vector >= 64)
|
||||
return 0;
|
||||
else if (vector < 192 && vector >= 128)
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool bsp_interrupt_is_valid_vector(rtems_vector_number vector)
|
||||
{
|
||||
return vector < BSP_INTERRUPT_VECTOR_COUNT;
|
||||
}
|
||||
|
||||
static uint32_t s_wasInstalled[6];
|
||||
|
||||
static bool bsp_interrupt_was_installed(int vector)
|
||||
{
|
||||
return !!(s_wasInstalled[vector/32] & (1<<vector%32));
|
||||
}
|
||||
|
||||
static void bsp_interrupt_mark_installed(int vector)
|
||||
{
|
||||
s_wasInstalled[vector/32] |= (1<<vector%32);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt controller allocation. Mark a level and priority used,
|
||||
* each interrupt must have a unique level/prio
|
||||
*/
|
||||
rtems_status_code bsp_allocate_interrupt(int level, int priority)
|
||||
{
|
||||
static char used[7];
|
||||
rtems_interrupt_level l;
|
||||
rtems_status_code ret = RTEMS_RESOURCE_IN_USE;
|
||||
|
||||
if ((level < 1) || (level > 7) || (priority < 0) || (priority > 7))
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
rtems_interrupt_disable(l);
|
||||
if ((used[level-1] & (1 << priority)) == 0) {
|
||||
used[level-1] |= (1 << priority);
|
||||
ret = RTEMS_SUCCESSFUL;
|
||||
}
|
||||
rtems_interrupt_enable(l);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void enable_irq(int which, int off)
|
||||
{
|
||||
if (off < 32) {
|
||||
*(which ? &MCF5282_INTC1_IMRL : &MCF5282_INTC0_IMRL) &=
|
||||
~(1<<off | MCF5282_INTC_IMRL_MASKALL);
|
||||
}
|
||||
else {
|
||||
*(which ? &MCF5282_INTC1_IMRH : &MCF5282_INTC0_IMRH) &= ~(1<<(off-32));
|
||||
}
|
||||
}
|
||||
|
||||
rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
|
||||
{
|
||||
int off;
|
||||
int which;
|
||||
int level;
|
||||
int prio;
|
||||
volatile uint8_t* reg;
|
||||
|
||||
if (!bsp_interrupt_is_valid_vector(vector))
|
||||
return RTEMS_UNSATISFIED;
|
||||
|
||||
if ((which = vector_to_source(vector)) < 0) {
|
||||
return RTEMS_SUCCESSFUL; /* nothing to do */
|
||||
}
|
||||
|
||||
off = vector_to_offset(vector);
|
||||
|
||||
/* check if the interrupt has already been setup */
|
||||
if (!bsp_interrupt_was_installed(vector)) {
|
||||
bsp_interrupt_mark_installed(vector);
|
||||
|
||||
/* attempt to map a unique priority/level to the interrupt. Uniqueness is
|
||||
* required, otherwise we get UB */
|
||||
for (level = 1; level < 8; level++) {
|
||||
for (prio = 0; prio < 8; prio++) {
|
||||
if (bsp_allocate_interrupt(level, prio) == RTEMS_SUCCESSFUL) {
|
||||
MCF5282_EPORT_EPIER;
|
||||
/* ICR1-8 are fixed level/prio. the rest need setup */
|
||||
if (off > 8) {
|
||||
reg = (which ? &MCF5282_INTC1_ICR09 - 8 : &MCF5282_INTC0_ICR1);
|
||||
reg += off - 1;
|
||||
|
||||
/* configure level and prio */
|
||||
*reg |= MCF5282_INTC_ICR_IL(level) |
|
||||
MCF5282_INTC_ICR_IP(prio);
|
||||
}
|
||||
|
||||
enable_irq(which, off);
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return RTEMS_UNSATISFIED;
|
||||
}
|
||||
|
||||
enable_irq(which, off);
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
rtems_status_code bsp_interrupt_get_attributes(
|
||||
rtems_vector_number vector,
|
||||
rtems_interrupt_attributes *attributes
|
||||
)
|
||||
{
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
rtems_status_code bsp_interrupt_is_pending(
|
||||
rtems_vector_number vector,
|
||||
bool *pending
|
||||
)
|
||||
{
|
||||
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
||||
bsp_interrupt_assert(pending != NULL);
|
||||
*pending = false;
|
||||
return RTEMS_UNSATISFIED;
|
||||
}
|
||||
|
||||
rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
|
||||
{
|
||||
int off;
|
||||
int which;
|
||||
|
||||
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
||||
|
||||
if ((which = vector_to_source(vector)) < 0) {
|
||||
return RTEMS_UNSATISFIED;
|
||||
}
|
||||
|
||||
off = vector_to_offset(vector);
|
||||
|
||||
if (off < 32)
|
||||
*(which ? &MCF5282_INTC1_INTFRCL : &MCF5282_INTC0_INTFRCL) |= (1<<off);
|
||||
else
|
||||
*(which ? &MCF5282_INTC1_INTFRCH : &MCF5282_INTC0_INTFRCH) |= (1<<(off-32));
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
|
||||
{
|
||||
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
||||
return RTEMS_UNSATISFIED;
|
||||
}
|
||||
|
||||
rtems_status_code bsp_interrupt_vector_is_enabled(
|
||||
rtems_vector_number vector,
|
||||
bool *enabled
|
||||
)
|
||||
{
|
||||
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
||||
bsp_interrupt_assert(enabled != NULL);
|
||||
*enabled = false;
|
||||
return RTEMS_UNSATISFIED;
|
||||
}
|
||||
|
||||
rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
|
||||
{
|
||||
int off;
|
||||
int which;
|
||||
|
||||
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
||||
|
||||
if ((which = vector_to_source(vector)) < 0) {
|
||||
return RTEMS_SUCCESSFUL; /* nothing to do */
|
||||
}
|
||||
|
||||
off = vector_to_offset(vector);
|
||||
|
||||
/* mask the interrupt */
|
||||
if (off < 32) {
|
||||
*(which ? &MCF5282_INTC1_IMRL : &MCF5282_INTC0_IMRL) |= 1<<off;
|
||||
}
|
||||
else {
|
||||
*(which ? &MCF5282_INTC1_IMRH : &MCF5282_INTC0_IMRH) |= 1<<(off-32);
|
||||
}
|
||||
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
rtems_status_code bsp_interrupt_set_priority(
|
||||
rtems_vector_number vector,
|
||||
uint32_t priority
|
||||
)
|
||||
{
|
||||
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
||||
return RTEMS_UNSATISFIED;
|
||||
}
|
||||
|
||||
rtems_status_code bsp_interrupt_get_priority(
|
||||
rtems_vector_number vector,
|
||||
uint32_t *priority
|
||||
)
|
||||
{
|
||||
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
||||
bsp_interrupt_assert(priority != NULL);
|
||||
return RTEMS_UNSATISFIED;
|
||||
}
|
||||
|
||||
void bsp_interrupt_facility_initialize(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void set_exception_handler(
|
||||
rtems_vector_number vector,
|
||||
void_func_t handler
|
||||
)
|
||||
{
|
||||
void **vbr;
|
||||
void_func_t *exception_table;
|
||||
|
||||
m68k_get_vbr(vbr);
|
||||
|
||||
exception_table = (void_func_t*)vbr;
|
||||
exception_table[vector] = handler;
|
||||
}
|
||||
|
||||
static void dispatch_handler(rtems_vector_number exception_vector)
|
||||
{
|
||||
bsp_interrupt_handler_dispatch_unchecked(exception_vector);
|
||||
}
|
||||
|
||||
void uC5282_interrupt_vector_install(rtems_vector_number vector)
|
||||
{
|
||||
_ISR_Vector_table[vector] = dispatch_handler;
|
||||
set_exception_handler(vector, _ISR_Handler);
|
||||
}
|
||||
|
||||
void uC5282_interrupt_vector_remove(rtems_vector_number vector)
|
||||
{
|
||||
set_exception_handler(vector, (void_func_t)bsp_default_isr_handler);
|
||||
}
|
||||
|
||||
/*
|
||||
* 'VME' interrupt support
|
||||
* Interrupt vectors 192-255 are set aside for use by external logic which
|
||||
* drives IRQ1*. The actual interrupt source is read from the external
|
||||
* logic at FPGA_IRQ_INFO. The most-significant bit of the least-significant
|
||||
* byte read from this location is set as long as the external logic has
|
||||
* interrupts to be serviced. The least-significant six bits indicate the
|
||||
* interrupt source within the external logic and are used to select the
|
||||
* specified interupt handler.
|
||||
*/
|
||||
#define FPGA_VECTOR (64+1) /* IRQ1* pin connected to external FPGA */
|
||||
#define FPGA_IRQ_INFO *((vuint16 *)(0x31000000 + 0xfffffe))
|
||||
|
||||
#define NVECTORS (BSP_INTERRUPT_VECTOR_COUNT + BSP_VME_INTERRUPT_VECTOR_COUNT)
|
||||
|
||||
static struct handlerTab {
|
||||
BSP_VME_ISR_t func;
|
||||
void *arg;
|
||||
} handlerTab[NVECTORS];
|
||||
|
||||
BSP_VME_ISR_t BSP_getVME_isr(unsigned long vector, void **pusrArg)
|
||||
{
|
||||
if (vector >= NVECTORS)
|
||||
return (BSP_VME_ISR_t)NULL;
|
||||
if (pusrArg)
|
||||
*pusrArg = handlerTab[vector].arg;
|
||||
return handlerTab[vector].func;
|
||||
}
|
||||
|
||||
/*
|
||||
* Trampoline for FPGA interrupts on the IRQ1* pin
|
||||
*/
|
||||
static void fpga_trampoline(void* arg)
|
||||
{
|
||||
rtems_vector_number v = (rtems_vector_number)arg;
|
||||
|
||||
/* ACK the interrupt */
|
||||
MCF5282_EPORT_EPFR |= MCF5282_EPORT_EPFR_EPF1;
|
||||
|
||||
/*
|
||||
* Handle FPGA interrupts until all have been consumed
|
||||
*/
|
||||
int loopcount = 0;
|
||||
while (((v = FPGA_IRQ_INFO) & 0x80) != 0) {
|
||||
v = 192 + (v & 0x3f);
|
||||
if (++loopcount >= 50) {
|
||||
rtems_interrupt_level level;
|
||||
rtems_interrupt_disable(level);
|
||||
printk(
|
||||
"\nTOO MANY FPGA INTERRUPTS (LAST WAS 0x%x) -- "
|
||||
"DISABLING ALL FPGA INTERRUPTS.\n",
|
||||
v & 0x3f
|
||||
);
|
||||
MCF5282_INTC0_IMRL |= MCF5282_INTC_IMRL_INT1;
|
||||
rtems_interrupt_enable(level);
|
||||
return;
|
||||
}
|
||||
|
||||
if (handlerTab[v].func) {
|
||||
(*handlerTab[v].func)(handlerTab[v].arg, (unsigned long)v);
|
||||
}
|
||||
else {
|
||||
rtems_interrupt_level level;
|
||||
rtems_vector_number nv;
|
||||
rtems_interrupt_disable(level);
|
||||
printk("\nSPURIOUS FPGA INTERRUPT (0x%x).\n", v & 0x3f);
|
||||
if ((((nv = FPGA_IRQ_INFO) & 0x80) != 0)
|
||||
&& ((nv & 0x3f) == (v & 0x3f))) {
|
||||
printk("DISABLING ALL FPGA INTERRUPTS.\n");
|
||||
MCF5282_INTC0_IMRL |= MCF5282_INTC_IMRL_INT1;
|
||||
}
|
||||
rtems_interrupt_enable(level);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Trampoline for legacy interrupts installed via BSP_installVME_isr
|
||||
*/
|
||||
static void trampoline(void* arg)
|
||||
{
|
||||
rtems_vector_number vec = (rtems_vector_number)arg;
|
||||
if (handlerTab[vec].func)
|
||||
(*handlerTab[vec].func)(handlerTab[vec].arg, (unsigned long)vec);
|
||||
}
|
||||
|
||||
int BSP_installVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *usrArg)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Register the handler information
|
||||
*/
|
||||
if (vector >= NVECTORS)
|
||||
return -1;
|
||||
|
||||
handlerTab[vector].func = handler;
|
||||
handlerTab[vector].arg = usrArg;
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
|
||||
/*
|
||||
* If this is an external FPGA ('VME') vector set up the real IRQ.
|
||||
*/
|
||||
if ((vector >= BSP_FIRST_VME_INTERRUPT_VECTOR) && (vector <= 255)) {
|
||||
static volatile int setupDone;
|
||||
if (setupDone) {
|
||||
rtems_interrupt_enable(level);
|
||||
return 0;
|
||||
}
|
||||
setupDone = 1;
|
||||
|
||||
i = rtems_interrupt_handler_install(
|
||||
FPGA_VECTOR,
|
||||
"fpga_trampoline",
|
||||
RTEMS_INTERRUPT_UNIQUE,
|
||||
fpga_trampoline,
|
||||
(void*)FPGA_VECTOR
|
||||
);
|
||||
|
||||
if (i == RTEMS_SUCCESSFUL)
|
||||
i = bsp_interrupt_vector_enable(FPGA_VECTOR);
|
||||
|
||||
/* enable IRQ1 EPORT interrupts as well */
|
||||
MCF5282_EPORT_EPIER |= MCF5282_EPORT_EPIER_EPIE1;
|
||||
|
||||
rtems_interrupt_enable(level);
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the connection between the interrupt and the local handler
|
||||
*/
|
||||
i = rtems_interrupt_handler_install(
|
||||
vector,
|
||||
"trampoline",
|
||||
RTEMS_INTERRUPT_UNIQUE,
|
||||
trampoline,
|
||||
(void*)vector
|
||||
);
|
||||
|
||||
if (i != RTEMS_SUCCESSFUL) {
|
||||
rtems_interrupt_enable(level);
|
||||
return i;
|
||||
}
|
||||
|
||||
/* for compatibility with older code: Enable IRQn interrupts on EPORT too.
|
||||
* This used to be done in init_intc0_bit */
|
||||
if (vector <= (64 + 7) && vector > 64) {
|
||||
MCF5282_EPORT_EPIER |= 1 << (vector - 64);
|
||||
}
|
||||
|
||||
i = bsp_interrupt_vector_enable(vector);
|
||||
|
||||
rtems_interrupt_enable(level);
|
||||
return i;
|
||||
}
|
||||
|
||||
int BSP_removeVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *usrArg)
|
||||
{
|
||||
if (vector >= NVECTORS)
|
||||
return -1;
|
||||
if ((handlerTab[vector].func != handler)
|
||||
|| (handlerTab[vector].arg != usrArg))
|
||||
return -1;
|
||||
handlerTab[vector].func = (BSP_VME_ISR_t)NULL;
|
||||
return 0;
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <bsp.h>
|
||||
#include <bsp/bootcard.h>
|
||||
#include <bsp/irq-generic.h>
|
||||
#include <rtems/error.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
@@ -322,6 +323,8 @@ void bsp_start( void )
|
||||
"System clock speed: %" PRIu32 "Hz\n", bsp_get_CPU_clock_speed()
|
||||
);
|
||||
}
|
||||
|
||||
bsp_interrupt_initialize();
|
||||
}
|
||||
|
||||
uint32_t bsp_get_CPU_clock_speed(void)
|
||||
@@ -329,27 +332,6 @@ uint32_t bsp_get_CPU_clock_speed(void)
|
||||
return( BSP_sys_clk_speed );
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt controller allocation
|
||||
*/
|
||||
rtems_status_code
|
||||
bsp_allocate_interrupt(int level, int priority)
|
||||
{
|
||||
static char used[7];
|
||||
rtems_interrupt_level l;
|
||||
rtems_status_code ret = RTEMS_RESOURCE_IN_USE;
|
||||
|
||||
if ((level < 1) || (level > 7) || (priority < 0) || (priority > 7))
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
rtems_interrupt_disable(l);
|
||||
if ((used[level-1] & (1 << priority)) == 0) {
|
||||
used[level-1] |= (1 << priority);
|
||||
ret = RTEMS_SUCCESSFUL;
|
||||
}
|
||||
rtems_interrupt_enable(l);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Arcturus bootloader system calls
|
||||
*/
|
||||
@@ -482,190 +464,6 @@ int BSP_disableVME_int_lvl(unsigned int level)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 'VME' interrupt support
|
||||
* Interrupt vectors 192-255 are set aside for use by external logic which
|
||||
* drives IRQ1*. The actual interrupt source is read from the external
|
||||
* logic at FPGA_IRQ_INFO. The most-significant bit of the least-significant
|
||||
* byte read from this location is set as long as the external logic has
|
||||
* interrupts to be serviced. The least-significant six bits indicate the
|
||||
* interrupt source within the external logic and are used to select the
|
||||
* specified interupt handler.
|
||||
*/
|
||||
#define NVECTOR 256
|
||||
#define FPGA_VECTOR (64+1) /* IRQ1* pin connected to external FPGA */
|
||||
#define FPGA_IRQ_INFO *((vuint16 *)(0x31000000 + 0xfffffe))
|
||||
|
||||
static struct handlerTab {
|
||||
BSP_VME_ISR_t func;
|
||||
void *arg;
|
||||
} handlerTab[NVECTOR];
|
||||
|
||||
BSP_VME_ISR_t
|
||||
BSP_getVME_isr(unsigned long vector, void **pusrArg)
|
||||
{
|
||||
if (vector >= NVECTOR)
|
||||
return (BSP_VME_ISR_t)NULL;
|
||||
if (pusrArg)
|
||||
*pusrArg = handlerTab[vector].arg;
|
||||
return handlerTab[vector].func;
|
||||
}
|
||||
|
||||
static rtems_isr
|
||||
fpga_trampoline (rtems_vector_number v)
|
||||
{
|
||||
/*
|
||||
* Handle FPGA interrupts until all have been consumed
|
||||
*/
|
||||
int loopcount = 0;
|
||||
while (((v = FPGA_IRQ_INFO) & 0x80) != 0) {
|
||||
v = 192 + (v & 0x3f);
|
||||
if (++loopcount >= 50) {
|
||||
rtems_interrupt_level level;
|
||||
rtems_interrupt_disable(level);
|
||||
printk(
|
||||
"\nTOO MANY FPGA INTERRUPTS (LAST WAS 0x%x) -- "
|
||||
"DISABLING ALL FPGA INTERRUPTS.\n",
|
||||
v & 0x3f
|
||||
);
|
||||
MCF5282_INTC0_IMRL |= MCF5282_INTC_IMRL_INT1;
|
||||
rtems_interrupt_enable(level);
|
||||
return;
|
||||
}
|
||||
if (handlerTab[v].func) {
|
||||
(*handlerTab[v].func)(handlerTab[v].arg, (unsigned long)v);
|
||||
}
|
||||
else {
|
||||
rtems_interrupt_level level;
|
||||
rtems_vector_number nv;
|
||||
rtems_interrupt_disable(level);
|
||||
printk("\nSPURIOUS FPGA INTERRUPT (0x%x).\n", v & 0x3f);
|
||||
if ((((nv = FPGA_IRQ_INFO) & 0x80) != 0)
|
||||
&& ((nv & 0x3f) == (v & 0x3f))) {
|
||||
printk("DISABLING ALL FPGA INTERRUPTS.\n");
|
||||
MCF5282_INTC0_IMRL |= MCF5282_INTC_IMRL_INT1;
|
||||
}
|
||||
rtems_interrupt_enable(level);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static rtems_isr
|
||||
trampoline (rtems_vector_number v)
|
||||
{
|
||||
if (handlerTab[v].func)
|
||||
(*handlerTab[v].func)(handlerTab[v].arg, (unsigned long)v);
|
||||
}
|
||||
|
||||
static void
|
||||
enable_irq(unsigned source)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
rtems_interrupt_disable(level);
|
||||
if (source >= 32)
|
||||
MCF5282_INTC0_IMRH &= ~(1 << (source - 32));
|
||||
else
|
||||
MCF5282_INTC0_IMRL &= ~((1 << source) |
|
||||
MCF5282_INTC_IMRL_MASKALL);
|
||||
rtems_interrupt_enable(level);
|
||||
}
|
||||
|
||||
static int
|
||||
init_intc0_bit(unsigned long vector)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
|
||||
/*
|
||||
* Find an unused level/priority if this is an on-chip (INTC0)
|
||||
* source and this is the first time the source is being used.
|
||||
* Interrupt sources 1 through 7 are fixed level/priority
|
||||
*/
|
||||
|
||||
if ((vector >= 65) && (vector <= 127)) {
|
||||
int l, p;
|
||||
int source = vector - 64;
|
||||
static unsigned char installed[8];
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
if (installed[source/8] & (1 << (source % 8))) {
|
||||
rtems_interrupt_enable(level);
|
||||
return 0;
|
||||
}
|
||||
installed[source/8] |= (1 << (source % 8));
|
||||
rtems_interrupt_enable(level);
|
||||
for (l = 1 ; l < 7 ; l++) {
|
||||
for (p = 0 ; p < 8 ; p++) {
|
||||
if ((source < 8)
|
||||
|| (bsp_allocate_interrupt(l,p) == RTEMS_SUCCESSFUL)) {
|
||||
if (source < 8)
|
||||
MCF5282_EPORT_EPIER |= 1 << source;
|
||||
else
|
||||
*(&MCF5282_INTC0_ICR1 + (source - 1)) =
|
||||
MCF5282_INTC_ICR_IL(l) |
|
||||
MCF5282_INTC_ICR_IP(p);
|
||||
enable_irq(source);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
BSP_installVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *usrArg)
|
||||
{
|
||||
rtems_isr_entry old_handler;
|
||||
rtems_interrupt_level level;
|
||||
|
||||
/*
|
||||
* Register the handler information
|
||||
*/
|
||||
if (vector >= NVECTOR)
|
||||
return -1;
|
||||
handlerTab[vector].func = handler;
|
||||
handlerTab[vector].arg = usrArg;
|
||||
|
||||
/*
|
||||
* If this is an external FPGA ('VME') vector set up the real IRQ.
|
||||
*/
|
||||
if ((vector >= 192) && (vector <= 255)) {
|
||||
int i;
|
||||
static volatile int setupDone;
|
||||
rtems_interrupt_disable(level);
|
||||
if (setupDone) {
|
||||
rtems_interrupt_enable(level);
|
||||
return 0;
|
||||
}
|
||||
setupDone = 1;
|
||||
rtems_interrupt_catch(fpga_trampoline, FPGA_VECTOR, &old_handler);
|
||||
i = init_intc0_bit(FPGA_VECTOR);
|
||||
rtems_interrupt_enable(level);
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the connection between the interrupt and the local handler
|
||||
*/
|
||||
rtems_interrupt_catch(trampoline, vector, &old_handler);
|
||||
|
||||
return init_intc0_bit(vector);
|
||||
}
|
||||
|
||||
int
|
||||
BSP_removeVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *usrArg)
|
||||
{
|
||||
if (vector >= NVECTOR)
|
||||
return -1;
|
||||
if ((handlerTab[vector].func != handler)
|
||||
|| (handlerTab[vector].arg != usrArg))
|
||||
return -1;
|
||||
handlerTab[vector].func = (BSP_VME_ISR_t)NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
BSP_vme2local_adrs(
|
||||
unsigned am, unsigned long vmeaddr, unsigned long *plocaladdr)
|
||||
|
||||
@@ -29,7 +29,7 @@ links:
|
||||
- role: build-dependency
|
||||
uid: ../../obj
|
||||
- role: build-dependency
|
||||
uid: ../../objirqdflt
|
||||
uid: ../../objirq
|
||||
- role: build-dependency
|
||||
uid: ../../objmem
|
||||
- role: build-dependency
|
||||
@@ -46,6 +46,8 @@ source:
|
||||
- bsps/m68k/uC5282/start/bspreset.c
|
||||
- bsps/m68k/uC5282/start/bspstart.c
|
||||
- bsps/m68k/uC5282/start/init5282.c
|
||||
- bsps/m68k/uC5282/irq/irq.c
|
||||
- bsps/shared/irq/irq-default-handler.c
|
||||
- bsps/shared/dev/getentropy/getentropy-cpucounter.c
|
||||
- bsps/shared/start/gettargethash-default.c
|
||||
- bsps/shared/start/sbrk.c
|
||||
|
||||
Reference in New Issue
Block a user