diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-23 09:50:39 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-23 15:18:44 +0200 |
commit | 8f8ccee0d9e1c3adfb1de484f26f6d9f6ff08708 (patch) | |
tree | 5dc76f7a4527b0a500fbf5ee91486b2780e47a1a /bsps/powerpc/gen5200 | |
parent | bsps: Move SPI drivers to bsps (diff) | |
download | rtems-8f8ccee0d9e1c3adfb1de484f26f6d9f6ff08708.tar.bz2 |
bsps: Move interrupt controller support to bsps
This patch is a part of the BSP source reorganization.
Update #3285.
Diffstat (limited to 'bsps/powerpc/gen5200')
-rw-r--r-- | bsps/powerpc/gen5200/irq/irq.c | 722 |
1 files changed, 722 insertions, 0 deletions
diff --git a/bsps/powerpc/gen5200/irq/irq.c b/bsps/powerpc/gen5200/irq/irq.c new file mode 100644 index 0000000000..11d9e3992e --- /dev/null +++ b/bsps/powerpc/gen5200/irq/irq.c @@ -0,0 +1,722 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC5200 BSP | ++-----------------------------------------------------------------+ +| Partially based on the code references which are named below. | +| Adaptions, modifications, enhancements and any recent parts of | +| the code are: | +| Copyright (c) 2005 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| 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. | +| | ++-----------------------------------------------------------------+ +| this file contains the irq controller handler | +\*===============================================================*/ +/***********************************************************************/ +/* */ +/* Module: irq.c */ +/* Date: 07/17/2003 */ +/* Purpose: RTEMS MPC5x00 CPU main interrupt handler & routines */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Description: This file contains the implementation of the */ +/* functions described in irq.h */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Code */ +/* References: MPC8260ads main interrupt handler & routines */ +/* Module: irc.c */ +/* Project: RTEMS 4.6.0pre1 / MCF8260ads BSP */ +/* Version 1.2 */ +/* Date: 04/18/2002 */ +/* */ +/* Author(s) / Copyright(s): */ +/* */ +/* Copyright (C) 1998, 1999 valette@crf.canon.fr */ +/* */ +/* Modified for mpc8260 Andy Dachs <a.dachs@sstl.co.uk> */ +/* Surrey Satellite Technology Limited, 2000 */ +/* Nested exception handlers not working yet. */ +/* */ +/* 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. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Partially based on the code references which are named above. */ +/* Adaptions, modifications, enhancements and any recent parts of */ +/* the code are under the right of */ +/* */ +/* IPR Engineering, Dachauer Straße 38, D-80335 München */ +/* Copyright(C) 2003 */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* IPR Engineering makes no representation or warranties with */ +/* respect to the performance of this computer program, and */ +/* specifically disclaims any responsibility for any damages, */ +/* special or consequential, connected with the use of this program. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Version history: 1.0 */ +/* */ +/***********************************************************************/ + +#include <inttypes.h> + +#include <rtems.h> + +#include <libcpu/powerpc-utility.h> +#include <bsp/vectors.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/mpc5200.h> + +/* + * bit in the SIU mask registers (PPC bit numbering) that should + * be set to enable the relevant interrupt, mask of 32 is for unused entries + * + */ +const static unsigned int SIU_MaskBit [BSP_SIU_IRQ_NUMBER] = { + 0, 1, 2, 3, /* smart_comm, psc1, psc2, psc3 */ + 4, 5, 6, 7, /* irda/psc6, eth, usb, ata */ + 8, 9, 10, 11, /* pci_ctrl, pci_sc_rx, pci_sc_tx, psc4 */ + 12, 13, 14, 15, /* psc5,spi_modf, spi_spif, i2c1 */ + 16, 17, 18, 19, /* i2c, can1, can2, ir_rx */ + 20, 21, 15, 16, /* ir_rx, xlb_arb, slice_tim2, irq1, */ + 17, 18, 19, 20, /* irq2, irq3, lo_int, rtc_pint */ + 21, 22, 23, 24, /* rtc_sint, gpio_std, gpio_wkup, tmr0 */ + 25, 26, 27, 28, /* tmr1, tmr2, tmr3, tmr4 */ + 29, 30, 31, 32, /* tmr5, tmr6, tmr7, res */ + 32, 32, 32 /* res, res, res */ +}; + +static unsigned char irqPrioTable [BSP_SIU_IRQ_NUMBER] = { +/* per. int. priorities (0-7) / 4bit coding / msb is HI/LO selection */ +/* msb = 0 -> non-critical per. int. is routed to main int. (LO_int) */ +/* msb = 1 -> critical per. int. is routed to critical int. (HI_int) */ + 0xF, 0, 0, 0, /* smart_comm (do not change!), psc1, psc2, psc3 */ + 0, 0, 0, 0, /* irda, eth, usb, ata */ + 0, 0, 0, 0, /* pci_ctrl, pci_sc_rx, pci_sc_tx, res */ + 0, 0, 0, 0, /* res, spi_modf, spi_spif, i2c1 */ + 0, 0, 0, 0, /* i2c, can1, can2, ir_rx */ + 0, 0, /* ir_rx, xlb_arb */ +/* main interrupt priorities (0-7) / 4bit coding / msb is INT/SMI selection */ +/* msb = 0 -> main int. is routed to processor INT (low vector base 0x500 ) */ +/* msb = 1 -> main int. is routed to processor SMI (low vector base 0x1400 ) */ + 0, 0, /* slice_tim2, irq1 */ + 0, 0, 0, 0, /* irq2, irq3, lo_int, rtc_pint */ + 0, 0, 0, 0, /* rtc_sint, gpio_std, gpio_wkup, tmr0 */ + 0, 0, 0, 0, /* tmr1, tmr2, tmr3, tmr4 */ + 0, 0, 0, /* tmr5, tmr6, tmr7 */ + /* critical interrupt priorities (0-3) / 2bit coding / no special purpose of msb */ + 0, /* irq0 */ + 0, 0, 0 /* slice_tim1, hi_int, ccs_wkup */ +}; + +static uint32_t irqMaskTable [BSP_PER_IRQ_NUMBER + BSP_MAIN_IRQ_NUMBER]; + +/* + * Check if symbolic IRQ name is a Processor IRQ + */ +static inline bool is_processor_irq( rtems_vector_number irqLine) +{ + + return ((irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) + && (irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET)); +} + +/* + * Check for SIU IRQ and return base index + */ +static inline bool is_siu_irq( rtems_vector_number irqLine) +{ + + return ((irqLine <= BSP_SIU_IRQ_MAX_OFFSET) + && (irqLine >= BSP_SIU_IRQ_LOWEST_OFFSET)); +} + +/* + * Check for SIU IRQ and return base index + */ +static inline int get_siu_irq_base_index( rtems_vector_number irqLine) +{ + if (irqLine <= BSP_PER_IRQ_MAX_OFFSET) + return BSP_PER_IRQ_LOWEST_OFFSET; + + if (irqLine <= BSP_MAIN_IRQ_MAX_OFFSET) + return BSP_MAIN_IRQ_LOWEST_OFFSET; + + if (irqLine <= BSP_CRIT_IRQ_MAX_OFFSET) + return BSP_CRIT_IRQ_LOWEST_OFFSET; + + return -1; +} + +static inline void BSP_enable_per_irq_at_siu( + rtems_vector_number irqLine +) +{ + uint8_t lo_hi_ind = 0, + prio_index_offset; + uint32_t *reg; + + /* calculate the index offset of priority value bit field */ + prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8; + + /* set interrupt priorities */ + if (irqPrioTable [irqLine] <= 15) { + + /* set peripheral int priority */ + reg = (uint32_t *) (&(mpc5200.per_pri_1)); + + /* choose proper register */ + reg += (irqLine >> 3); + + /* set priority as given in priority table */ + *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2))); + + /* test msb (hash-bit) and set LO_/HI_int indicator */ + if ((lo_hi_ind = (irqPrioTable [irqLine] >> 3))) { + + /* set critical HI_int priority */ + reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask)); + *reg |= (irqPrioTable [BSP_SIU_IRQ_HI_INT] << 26); + + /* + * critical interrupt handling for the 603le core is not + * yet supported, routing of critical interrupts is forced + * to core_int (bit 31 / CEb) + */ + mpc5200.ext_en_type |= 1; + + } else { + if (irqPrioTable [irqLine] <= 15) { + /* set main LO_int priority */ + reg = (uint32_t *) (&(mpc5200.main_pri_1)); + *reg |= (irqPrioTable [BSP_SIU_IRQ_LO_INT] << 16); + } + } + } + + /* if LO_int ind., enable (unmask) main interrupt */ + if (!lo_hi_ind) { + mpc5200.crit_pri_main_mask &= + ~(0x80000000 >> SIU_MaskBit [BSP_SIU_IRQ_LO_INT]); + } + + /* enable (unmask) peripheral interrupt */ + mpc5200.per_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]); + + /* FIXME: Why? */ + mpc5200.main_pri_1; + mpc5200.crit_pri_main_mask; + mpc5200.per_pri_1; + mpc5200.per_mask; +} + +static inline void BSP_enable_main_irq_at_siu( + rtems_vector_number irqLine +) +{ + + uint8_t prio_index_offset; + uint32_t *reg; + + /* calculate the index offset of priority value bit field */ + prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8; + + /* set main interrupt priority */ + if (irqPrioTable [irqLine] <= 15) { + + /* set main int priority */ + reg = (uint32_t *) (&(mpc5200.main_pri_1)); + + /* choose proper register */ + reg += (irqLine >> 3); + + /* set priority as given in priority table */ + *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2))); + + if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) { + /* enable external irq-pin */ + mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset)); + } + } + + /* enable (unmask) main interrupt */ + mpc5200.crit_pri_main_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]); + +} + +static inline void BSP_enable_crit_irq_at_siu( + rtems_vector_number irqLine +) +{ + uint8_t prio_index_offset; + uint32_t *reg; + + prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET; + + /* + * critical interrupt handling for the 603Le core is not + * yet supported, routing of critical interrupts is forced + * to core_int (bit 31 / CEb) + */ + mpc5200.ext_en_type |= 1; + + /* set critical interrupt priorities */ + if (irqPrioTable [irqLine] <= 3) { + + /* choose proper register */ + reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask)); + + /* set priority as given in priority table */ + *reg |= (irqPrioTable [irqLine] << (30 - (prio_index_offset << 1))); + + /* external irq0-pin */ + if (irqLine == BSP_SIU_IRQ_IRQ1) { + /* enable external irq-pin */ + mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset)); + } + } +} + +static inline void BSP_disable_per_irq_at_siu( + rtems_vector_number irqLine +) +{ + uint8_t prio_index_offset; + uint32_t *reg; + + /* calculate the index offset of priority value bit field */ + prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8; + + /* disable (mask) peripheral interrupt */ + mpc5200.per_mask |= (0x80000000 >> SIU_MaskBit [irqLine]); + + /* reset priority to lowest level (reset value) */ + reg = (uint32_t *) (&(mpc5200.per_pri_1)); + reg += (irqLine >> 3); + *reg &= ~(15 << (28 - (prio_index_offset << 2))); +} + +static inline void BSP_disable_main_irq_at_siu( + rtems_vector_number irqLine +) +{ + uint8_t prio_index_offset; + uint32_t *reg; + + /* calculate the index offset of priority value bit field */ + prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8; + + /* disable (mask) main interrupt */ + mpc5200.crit_pri_main_mask |= (0x80000000 >> SIU_MaskBit [irqLine]); + + if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) { + /* disable external irq-pin */ + mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset)); + } + + /* reset priority to lowest level (reset value) */ + reg = (uint32_t *) (&(mpc5200.main_pri_1)); + reg += (irqLine >> 3); + *reg &= ~(15 << (28 - (prio_index_offset << 2))); +} + +static inline void BSP_disable_crit_irq_at_siu( rtems_vector_number + irqLine) +{ + uint8_t prio_index_offset; + uint32_t *reg; + + prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET; + + /* reset critical int priority to lowest level (reset value) */ + reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask)); + *reg &= ~(3 << (30 - (prio_index_offset << 1))); + + if (irqLine == BSP_SIU_IRQ_IRQ1) { + /* disable external irq0-pin */ + mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset)); + } +} + +/* + * This function enables a given siu interrupt + */ +void bsp_interrupt_vector_enable( rtems_vector_number vector) +{ + int base_index = get_siu_irq_base_index( vector); + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if (is_siu_irq( vector)) { + rtems_interrupt_level level; + + rtems_interrupt_disable( level); + + switch (base_index) { + case BSP_PER_IRQ_LOWEST_OFFSET: + BSP_enable_per_irq_at_siu( vector); + break; + case BSP_MAIN_IRQ_LOWEST_OFFSET: + BSP_enable_main_irq_at_siu( vector); + break; + case BSP_CRIT_IRQ_LOWEST_OFFSET: + BSP_enable_crit_irq_at_siu( vector); + break; + default: + bsp_interrupt_assert(0); + break; + } + + rtems_interrupt_enable( level); + } +} + +/* + * This function disables a given siu interrupt + */ +void bsp_interrupt_vector_disable( rtems_vector_number vector) +{ + int base_index = get_siu_irq_base_index( vector); + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if (is_siu_irq( vector)) { + rtems_interrupt_level level; + + rtems_interrupt_disable( level); + + switch (base_index) { + case BSP_PER_IRQ_LOWEST_OFFSET: + BSP_disable_per_irq_at_siu( vector); + break; + case BSP_MAIN_IRQ_LOWEST_OFFSET: + BSP_disable_main_irq_at_siu( vector); + break; + case BSP_CRIT_IRQ_LOWEST_OFFSET: + BSP_disable_crit_irq_at_siu( vector); + break; + default: + bsp_interrupt_assert(0); + break; + } + + rtems_interrupt_enable( level); + } +} + +#if (BENCHMARK_IRQ_PROCESSING == 0) +void BSP_IRQ_Benchmarking_Reset( void) +{ +} +void BSP_IRQ_Benchmarking_Report( void) +{ +} +#else +#include <stdio.h> +uint64_t BSP_Starting_TBR; +uint64_t BSP_Total_in_ISR; +uint32_t BSP_ISR_Count; +uint32_t BSP_Worst_ISR; + +#define BSP_COUNTED_IRQ 16 +uint32_t BSP_ISR_Count_Per [BSP_COUNTED_IRQ + 1]; + +void BSP_IRQ_Benchmarking_Reset( void) +{ + int i; + + BSP_Starting_TBR = PPC_Get_timebase_register(); + BSP_Total_in_ISR = 0; + BSP_ISR_Count = 0; + BSP_Worst_ISR = 0; + for (i = 0; i < BSP_COUNTED_IRQ; i++) + BSP_ISR_Count_Per [i] = 0; +} + +static const char *u64tostring( char *buffer, uint64_t v) +{ + sprintf( buffer, "%lld cycles %lld usecs", v, (v / 33)); + return buffer; +} + +void BSP_IRQ_Benchmarking_Report( void) +{ + uint64_t now; + char buffer [96]; + int i; + + now = PPC_Get_timebase_register(); + printk( "Started at: %s\n", u64tostring( buffer, BSP_Starting_TBR)); + printk( "Current : %s\n", u64tostring( buffer, now)); + printk( "System up : %s\n", u64tostring( buffer, now - BSP_Starting_TBR)); + printk( "ISRs : %d\n", BSP_ISR_Count); + printk( "ISRs ran : %s\n", u64tostring( buffer, BSP_Total_in_ISR)); + printk( "Worst ISR : %s\n", u64tostring( buffer, BSP_Worst_ISR)); + for (i = 0; i < BSP_COUNTED_IRQ; i++) + printk( "IRQ %d: %d\n", i, BSP_ISR_Count_Per [i]); + printk( "Ticks : %d\n", Clock_driver_ticks); +} +#endif + +static void dispatch(uint32_t irq, uint32_t offset, volatile uint32_t *maskreg) +{ + #if (ALLOW_IRQ_NESTING == 1) + uint32_t msr; + uint32_t mask = *maskreg; + #endif + + irq += offset; + + #if (ALLOW_IRQ_NESTING == 1) + *maskreg = mask | irqMaskTable [irq]; + /* Make sure that the write operation completed (cache inhibited area) */ + *maskreg; + msr = ppc_external_exceptions_enable(); + #endif + + bsp_interrupt_handler_dispatch(irq); + + #if (ALLOW_IRQ_NESTING == 1) + ppc_external_exceptions_disable(msr); + *maskreg = mask; + #endif +} + +/* + * High level IRQ handler called from shared_raw_irq_code_entry + */ +static int C_dispatch_irq_handler(BSP_Exception_frame *frame, unsigned excNum) +{ + uint32_t irq; + uint32_t pmce; + +#if (BENCHMARK_IRQ_PROCESSING == 1) + uint64_t start, + stop, + thisTime; + + start = PPC_Get_timebase_register(); + BSP_ISR_Count++; + if (excNum < BSP_COUNTED_IRQ) + BSP_ISR_Count_Per [excNum]++; + else + printk( "not counting %d\n", excNum); +#endif + + /* get the content of main interrupt status register */ + pmce = mpc5200.pmce; + + /* critical interrupts are routed to the core_int, see premature + * initialization + */ + while ((pmce & (PMCE_CSE_STICKY | PMCE_MSE_STICKY)) != 0) { + /* first: check for critical interrupt sources (hierarchical order) + * -> HI_int indicates peripheral sources + */ + if ((pmce & PMCE_CSE_STICKY) != 0) { + /* get source of critical interrupt */ + irq = PMCE_CSE_SOURCE(pmce); + + switch (irq) { + /* peripheral HI_int interrupt source detected */ + case 2: + /* check for valid peripheral interrupt source */ + if ((pmce & PMCE_PSE_STICKY) != 0) { + /* get source of peripheral interrupt */ + irq = PMCE_PSE_SOURCE(pmce); + + dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask); + } else { + /* this case may not occur: no valid peripheral + * interrupt source */ + printk( "No valid peripheral HI_int interrupt source\n"); + } + break; + + /* irq0, slice timer 1 or ccs wakeup detected */ + case 0: + case 1: + case 3: + + /* add proper offset for critical interrupts in the siu + * handler array */ + irq += BSP_CRIT_IRQ_LOWEST_OFFSET; + + /* Dispatch interrupt handlers */ + bsp_interrupt_handler_dispatch( irq); + + break; + + default: + /* error: unknown interrupt source */ + printk( "Unknown HI_int interrupt source\n"); + break; + } + } + + /* second: check for main interrupt sources (hierarchical order) + * -> LO_int indicates peripheral sources */ + if ((pmce & PMCE_MSE_STICKY) != 0) { + /* get source of main interrupt */ + irq = PMCE_MSE_SOURCE(pmce); + + if (irq == 4) { + /* peripheral LO_int interrupt source detected */ + /* check for valid peripheral interrupt source */ + if ((pmce & PMCE_PSE_STICKY) != 0) { + /* get source of peripheral interrupt */ + irq = PMCE_PSE_SOURCE(pmce); + + dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask); + } else { + /* this case may not occur: no valid peripheral + * interrupt source */ + printk( "No valid peripheral LO_int interrupt source\n"); + } + } else if (irq <= 16) { + /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer + * 2 is always routed to SMI) */ + dispatch(irq, BSP_MAIN_IRQ_LOWEST_OFFSET, &mpc5200.crit_pri_main_mask); + } else { + /* error: unknown interrupt source */ + printk( "Unknown peripheral LO_int interrupt source\n"); + } + } + + /* force re-evaluation of interrupts */ + mpc5200.pmce = PMCE_CSE_STICKY | PMCE_MSE_STICKY | PMCE_PSE_STICKY; + + /* get the content of main interrupt status register */ + pmce = mpc5200.pmce; + } + +#if (BENCHMARK_IRQ_PROCESSING == 1) + stop = PPC_Get_timebase_register(); + thisTime = stop - start; + BSP_Total_in_ISR += thisTime; + if (thisTime > BSP_Worst_ISR) + BSP_Worst_ISR = thisTime; +#endif + + return 0; +} + +/* + * setup irqMaskTable to support a priorized/nested interrupt environment + */ +static void setup_irqMaskTable( void) +{ + rtems_irq_prio prio = 0; + uint32_t i = 0, + j = 0, + mask = 0; + + /* set up the priority dependent masks for peripheral interrupts */ + for (i = BSP_PER_IRQ_LOWEST_OFFSET; i <= BSP_PER_IRQ_MAX_OFFSET; i++) { + prio = irqPrioTable [i]; + mask = 0; + + for (j = BSP_PER_IRQ_LOWEST_OFFSET; j <= BSP_PER_IRQ_MAX_OFFSET; j++) { + if (prio > irqPrioTable [j]) { + mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET)); + } + + if ((prio == irqPrioTable [j]) && (j >= i)) { + mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET)); + } + } + + irqMaskTable [i] = mask; + } + + /* set up the priority dependent masks for main interrupts */ + for (i = BSP_MAIN_IRQ_LOWEST_OFFSET; i <= BSP_MAIN_IRQ_MAX_OFFSET; i++) { + prio = irqPrioTable [i]; + mask = 0; + + for (j = BSP_MAIN_IRQ_LOWEST_OFFSET; j <= BSP_MAIN_IRQ_MAX_OFFSET; j++) { + if (prio > irqPrioTable [j]) { + mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET)); + } + + if ((prio == irqPrioTable [j]) && (j >= i)) { + mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET)); + } + } + + irqMaskTable [i] = mask; + } +} + +/* + * Initialize MPC5x00 SIU interrupt management + */ +static void BSP_SIU_irq_init( void) +{ + + /* disable all peripheral interrupts */ + mpc5200.per_mask = 0xFFFFFC00; + + /* peripheral interrupt priorities according to reset value */ + mpc5200.per_pri_1 = 0xF0000000; + mpc5200.per_pri_2 = 0x00000000; + mpc5200.per_pri_3 = 0x00000000; + + /* disable external interrupts IRQ0-4 / critical interrupts are routed to core_int */ + mpc5200.ext_en_type = 0x0F000001; + + /* disable main interrupts / crit. int. priorities according to reset values */ + mpc5200.crit_pri_main_mask = 0x0001FFFF; + + /* main priorities according to reset value */ + mpc5200.main_pri_1 = 0; + mpc5200.main_pri_2 = 0; + + /* reset all status indicators */ + mpc5200.csa = 0x0001FFFF; + mpc5200.msa = 0x0001FFFF; + mpc5200.psa = 0x003FFFFF; + mpc5200.psa_be = 0x03000000; + + setup_irqMaskTable(); +} + +rtems_status_code bsp_interrupt_facility_initialize( void) +{ + BSP_SIU_irq_init(); + + /* Install exception handler */ + if (ppc_exc_set_handler( ASM_EXT_VECTOR, C_dispatch_irq_handler)) { + return RTEMS_IO_ERROR; + } + if (ppc_exc_set_handler( ASM_E300_SYSMGMT_VECTOR, C_dispatch_irq_handler)) { + return RTEMS_IO_ERROR; + } + + return RTEMS_SUCCESSFUL; +} + +void bsp_interrupt_handler_default( rtems_vector_number vector) +{ + if (vector != BSP_DECREMENTER) { + printk( "Spurious interrupt: 0x%08" PRIx32 "\n", vector); + } +} |