diff options
author | Ralf Corsepius <ralf.corsepius@rtems.org> | 2005-12-31 05:09:26 +0000 |
---|---|---|
committer | Ralf Corsepius <ralf.corsepius@rtems.org> | 2005-12-31 05:09:26 +0000 |
commit | ca680bc5890abe0d6bfe7eb4a40a0229f1b6bd36 (patch) | |
tree | 805a5ddce1250235d6133376ddabb5543eb2cf82 /c/src/lib/libbsp/powerpc/gen5200/irq | |
parent | Add BuildRoot. (diff) | |
download | rtems-ca680bc5890abe0d6bfe7eb4a40a0229f1b6bd36.tar.bz2 |
New (CVS import Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>'s
submission).
Diffstat (limited to 'c/src/lib/libbsp/powerpc/gen5200/irq')
-rw-r--r-- | c/src/lib/libbsp/powerpc/gen5200/irq/irq.c | 1141 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/gen5200/irq/irq.h | 411 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/gen5200/irq/irq_asm.S | 445 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/gen5200/irq/irq_init.c | 327 |
4 files changed, 2324 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c b/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c new file mode 100644 index 0000000000..2cde1fe025 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c @@ -0,0 +1,1141 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC5200 BSP | ++-----------------------------------------------------------------+ +| File: irq.c ++-----------------------------------------------------------------+ +| 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.com/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the irq controller handler | ++-----------------------------------------------------------------+ +| date history ID | +| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | +| 01.12.05 creation doe | +|*****************************************************************| +|*CVS information: | +|*(the following information is created automatically, | +|*do not edit here) | +|*****************************************************************| +|* $Log$ +|* Revision 1.6 2005/12/09 08:57:03 thomas +|* added/modifed file headers +|* +|* Revision 1.5 2005/12/06 14:30:42 thomas +|* updated name for peripheral register block +|* +|* Revision 1.4 2005/12/06 14:11:12 thomas +|* added EB file headers +|* + * +|*****************************************************************| +\*===============================================================*/ +/***********************************************************************/ +/* */ +/* 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 found in the file LICENSE in this distribution or at */ +/* http://www.OARcorp.com/rtems/license.html. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* 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 "../include/bsp.h"*/ +#include "../include/bsp.h" +#include <rtems.h> +/*#include "../irq/irq.h"*/ +#include "../irq/irq.h" +/*#include <rtems/score/thread.h>*/ +#include <rtems/score/apiext.h> +#include <rtems/bspIo.h> +#include "../include/raw_exception.h" +#include "../vectors/vectors.h" +#include "../include/mpc5200.h" + + +extern uint32_t irqMaskTable[]; + +/* + * default handler connected on each irq after bsp initialization + */ +static rtems_irq_connect_data default_rtems_entry; + +/* + * location used to store initial tables used for interrupt + * management. + */ +static rtems_irq_global_settings* internal_config; +static rtems_irq_connect_data* rtems_hdl_tbl; + +/* + * 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 */ + }; + +/* + * Check if symbolic IRQ name is a Processor IRQ + */ +static inline int is_processor_irq(const rtems_irq_symbolic_name irqLine) + { + + return (((int)irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) & ((int)irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET)); + + } + +/* + * Check for SIU IRQ and return base index + */ +static inline int is_siu_irq(const rtems_irq_symbolic_name irqLine) + { + + return (((int)irqLine <= BSP_SIU_IRQ_MAX_OFFSET) && ((int)irqLine >= BSP_SIU_IRQ_LOWEST_OFFSET)); + + } + + +/* + * Check for SIU IRQ and return base index + */ +static inline int get_siu_irq_base_index(const rtems_irq_symbolic_name irqLine) + { + + if(irqLine <= BSP_PER_IRQ_MAX_OFFSET) + return BSP_PER_IRQ_LOWEST_OFFSET; + else + if(irqLine <= BSP_MAIN_IRQ_MAX_OFFSET) + return BSP_MAIN_IRQ_LOWEST_OFFSET; + else + if(irqLine <= BSP_CRIT_IRQ_MAX_OFFSET) + return BSP_CRIT_IRQ_LOWEST_OFFSET; + else + return -1; + + } + + +static inline void BSP_enable_per_irq_at_siu(const rtems_irq_symbolic_name irqLine) + { + uint8_t lo_hi_ind = 0, prio_index_offset; + uint32_t *reg; + rtems_irq_prio *irqPrioTable = internal_config->irqPrioTbl; + volatile uint32_t per_pri_1,main_pri_1, crit_pri_main_mask, per_mask; + + /* 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]); + + main_pri_1 = mpc5200.main_pri_1; + crit_pri_main_mask = mpc5200.crit_pri_main_mask; + per_pri_1 = mpc5200.per_pri_1; + per_mask = mpc5200.per_mask; + + + } + + +static inline void BSP_enable_main_irq_at_siu(const rtems_irq_symbolic_name irqLine) + { + + uint8_t prio_index_offset; + uint32_t *reg; + rtems_irq_prio *irqPrioTable = internal_config->irqPrioTbl; + + /* 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(const rtems_irq_symbolic_name irqLine) + { + + uint8_t prio_index_offset; + uint32_t *reg; + rtems_irq_prio *irqPrioTable = internal_config->irqPrioTbl; + + 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(const rtems_irq_symbolic_name 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(const rtems_irq_symbolic_name 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(const rtems_irq_symbolic_name 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)); + + } + + } + + +/* + * ------------------------ RTEMS Irq helper functions ---------------- + */ + + +/* + * This function check that the value given for the irq line + * is valid. + */ +static int isValidInterrupt(int irq) + { + if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET) ) + return 0; + return 1; + } + + + /* + * This function enables a given siu interrupt + */ +int BSP_irq_enable_at_siu(const rtems_irq_symbolic_name irqLine) + { + int base_index; + + if(is_siu_irq(irqLine)) + { + + + if((base_index = get_siu_irq_base_index(irqLine)) != -1) + { + + switch(base_index) + { + + case BSP_PER_IRQ_LOWEST_OFFSET: + BSP_enable_per_irq_at_siu(irqLine); + break; + + case BSP_MAIN_IRQ_LOWEST_OFFSET: + BSP_enable_main_irq_at_siu(irqLine); + break; + + case BSP_CRIT_IRQ_LOWEST_OFFSET: + BSP_enable_crit_irq_at_siu(irqLine); + break; + + default: + printk("No valid base index\n"); + break; + + } + + } + + } + + return 0; + + } + +/* + * This function disables a given siu interrupt + */ +int BSP_irq_disable_at_siu(const rtems_irq_symbolic_name irqLine) + { + int base_index; + + if ( (base_index = get_siu_irq_base_index(irqLine)) == -1) + return 1; + + switch(base_index) + { + + case BSP_PER_IRQ_LOWEST_OFFSET: + BSP_disable_per_irq_at_siu(irqLine); + + break; + + case BSP_MAIN_IRQ_LOWEST_OFFSET: + BSP_disable_main_irq_at_siu(irqLine); + break; + + case BSP_CRIT_IRQ_LOWEST_OFFSET: + BSP_disable_crit_irq_at_siu(irqLine); + break; + + default: + printk("No valid base index\n"); + break; + + } + + return 0; + } + + +/* + * ------------------------ RTEMS Single Irq Handler Mngt Routines ---------------- + */ + + /* + * This function removes the default entry and installs a device interrupt handler + */ +int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq) + { + unsigned int level; + + if(!isValidInterrupt(irq->name)) + { + + printk("not a valid interrupt\n"); + return 0; + + } + + /* + * Check if default handler is actually connected. If not issue an error. + * RATIONALE : to always have the same transition by forcing the user + * to get the previous handler before accepting to disconnect. + */ + if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) + { + + printk( "Default handler not there\n" ); + return 0; + + } + + _CPU_ISR_Disable(level); + + /* + * store the data provided by user + */ + rtems_hdl_tbl[irq->name] = *irq; + + if(is_siu_irq(irq->name)) + { + + /* + * Enable interrupt at siu level + */ + BSP_irq_enable_at_siu(irq->name); + + } + else + { + + if(is_processor_irq(irq->name)) + { + + /* + * Should Enable exception at processor level but not needed. Will restore + * EE flags at the end of the routine anyway. + */ + + + } + else + { + + printk("not a valid interrupt\n"); + return 0; + + } + + } + + + /* + * Enable interrupt on device + */ + irq->on(irq); + + _CPU_ISR_Enable(level); + + return 1; + + } + + + /* + * This function procures the current interrupt handler + */ +int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq) + { + + if(!isValidInterrupt(irq->name)) + { + + return 0; + + } + + *irq = rtems_hdl_tbl[irq->name]; + return 1; + + } + + + /* + * This function removes a device interrupt handler and restores the default entry + */ +int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) + { + unsigned int level; + + if(!isValidInterrupt(irq->name)) + { + + return 0; + + } + + /* + * Check if default handler is actually connected. If not issue an error. + * RATIONALE : to always have the same transition by forcing the user + * to get the previous handler before accepting to disconnect. + */ + if(rtems_hdl_tbl[irq->name].hdl != irq->hdl) + { + + return 0; + + } + + _CPU_ISR_Disable(level); + + if(is_siu_irq(irq->name)) + { + + /* + * disable interrupt at PIC level + */ + BSP_irq_disable_at_siu(irq->name); + + } + + if(is_processor_irq(irq->name)) + { + /* + * disable exception at processor level + */ + } + + /* + * Disable interrupt on device + */ + irq->off(irq); + + /* + * restore the default irq value + */ + rtems_hdl_tbl[irq->name] = default_rtems_entry; + + _CPU_ISR_Enable(level); + + return 1; + + } + + +/* + * ------------------------ RTEMS Global Irq Handler Mngt Routines ---------------- + */ + +/* + * This function set up interrupt management dependent on the given configuration + */ +int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config) + { + int i; + unsigned int level; + + /* + * Store various code accelerators + */ + internal_config = config; + default_rtems_entry = config->defaultEntry; + rtems_hdl_tbl = config->irqHdlTbl; + + _CPU_ISR_Disable(level); + + /* + * start with SIU IRQs + */ + for (i=BSP_SIU_IRQ_LOWEST_OFFSET; i < BSP_SIU_IRQ_LOWEST_OFFSET + BSP_SIU_IRQ_NUMBER ; i++) + { + + if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) + { + + BSP_irq_enable_at_siu(i); + rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]); + + } + else + { + + rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); + BSP_irq_disable_at_siu(i); + + } + + } + + /* + * finish with Processor exceptions handled like IRQs + */ + for (i=BSP_PROCESSOR_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER; i++) + { + + if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) + { + + rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]); + + } + else + { + + rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); + + } + + } + + _CPU_ISR_Enable(level); + return 1; + + } + + +int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config) + { + + *config = internal_config; + return 0; + + } + + +/* + * High level IRQ handler called from shared_raw_irq_code_entry + */ +void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum) + { + register unsigned int irq; + register unsigned int msr; + register unsigned int new_msr; + register unsigned int pmce; + register unsigned int crit_pri_main_mask, per_mask; + + switch(excNum) + { + + + /* + * Handle decrementer interrupt + */ + case ASM_DEC_VECTOR: + + /* call the module specific handler and pass the specific handler */ + rtems_hdl_tbl[BSP_DECREMENTER].hdl(0); + + return; + + case ASM_SYSMGMT_VECTOR: + + /* get the content of main interrupt status register */ + pmce = mpc5200.pmce; + + /* main interrupts may be routed to SMI, see bit SMI/INT select bit in main int. priorities */ + while(CHK_MSE_STICKY(pmce)) + { + + /* check for main interrupt sources (hirarchical order) -> LO_int indicates peripheral sources */ + if(CHK_MSE_STICKY(pmce)) + { + + /* get source of main interrupt */ + irq = MSE_SOURCE(pmce); + + switch(irq) + { + + /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer 2 is always routed to SMI) */ + case 0: /* slice timer 2 */ + case 1: + case 2: + case 3: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + + /* add proper offset for main interrupts in the siu handler array */ + irq += BSP_MAIN_IRQ_LOWEST_OFFSET; + + /* save original mask and disable all lower priorized main interrupts*/ + crit_pri_main_mask = mpc5200.crit_pri_main_mask; + mpc5200.crit_pri_main_mask |= irqMaskTable[irq]; + + /* enable interrupt nesting */ + _CPU_MSR_GET(msr); + new_msr = msr | MSR_EE; + _CPU_MSR_SET(new_msr); + + /* call the module specific handler and pass the specific handler */ + rtems_hdl_tbl[irq].hdl(0); + + /* disable interrupt nesting */ + _CPU_MSR_SET(msr); + + /* restore original interrupt mask */ + mpc5200.crit_pri_main_mask = crit_pri_main_mask; + + break; + + /* peripheral LO_int interrupt source detected */ + case 4: + + /* check for valid peripheral interrupt source */ + if(CHK_PSE_STICKY(pmce)) + { + + /* get source of peripheral interrupt */ + irq = PSE_SOURCE(pmce); + + /* add proper offset for peripheral interrupts in the siu handler array */ + irq += BSP_PER_IRQ_LOWEST_OFFSET; + + /* save original mask and disable all lower priorized main interrupts */ + per_mask = mpc5200.per_mask; + mpc5200.per_mask |= irqMaskTable[irq]; + + /* enable interrupt nesting */ + _CPU_MSR_GET(msr); + new_msr = msr | MSR_EE; + _CPU_MSR_SET(new_msr); + + /* call the module specific handler and pass the specific handler */ + rtems_hdl_tbl[irq].hdl(0); + + + /* disable interrupt nesting */ + _CPU_MSR_SET(msr); + + /* restore original interrupt mask */ + mpc5200.per_mask = per_mask; + + /* force re-evaluation of peripheral interrupts */ + CLR_PSE_STICKY(mpc5200.pmce); + + } + /* this case may not occur: no valid peripheral interrupt source */ + else + { + + printk("No valid peripheral LO_int interrupt source\n"); + + } + + break; + + /* error: unknown interrupt source */ + default: + printk("Unknown peripheral LO_int interrupt source\n"); + break; + + } + + /* force re-evaluation of main interrupts */ + CLR_MSE_STICKY(mpc5200.pmce); + + } + + /* get the content of main interrupt status register */ + pmce = mpc5200.pmce; + + } + + break; + + case ASM_EXT_VECTOR: + + /* get the content of main interrupt status register */ + pmce = mpc5200.pmce; + + /* critical interrupts may be routed to the core_int dependent on premature initialization, see bit 31 (CEbsH) */ + while((CHK_CE_SHADOW(pmce) && CHK_CSE_STICKY(pmce)) || CHK_MSE_STICKY(pmce) || CHK_PSE_STICKY(pmce) ) + { + + /* first: check for critical interrupt sources (hirarchical order) -> HI_int indicates peripheral sources */ + if(CHK_CE_SHADOW(pmce) && CHK_CSE_STICKY(pmce)) + { + + /* get source of critical interrupt */ + irq = CSE_SOURCE(pmce); + + switch(irq) + { + /* 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; + + /* call the module specific handler and pass the specific handler */ + rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle); + + break; + + /* peripheral HI_int interrupt source detected */ + case 2: + + /* check for valid peripheral interrupt source */ + if(CHK_PSE_STICKY(pmce)) + { + + /* get source of peripheral interrupt */ + irq = PSE_SOURCE(pmce); + + /* add proper offset for peripheral interrupts in the siu handler array */ + irq += BSP_PER_IRQ_LOWEST_OFFSET; + + /* save original mask and disable all lower priorized main interrupts */ + per_mask = mpc5200.per_mask; + mpc5200.per_mask |= irqMaskTable[irq]; + + /* enable interrupt nesting */ + _CPU_MSR_GET(msr); + new_msr = msr | MSR_EE; + _CPU_MSR_SET(new_msr); + + /* call the module specific handler and pass the specific handler */ + rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle); + + + /* disable interrupt nesting */ + _CPU_MSR_SET(msr); + + /* restore original interrupt mask */ + mpc5200.per_mask = per_mask; + + /* force re-evaluation of peripheral interrupts */ + CLR_PSE_STICKY(mpc5200.pmce); + + } + /* this case may not occur: no valid peripheral interrupt source */ + else + { + + printk("No valid peripheral HI_int interrupt source\n"); + + } + + break; + + /* error: unknown interrupt source */ + default: + printk("Unknown HI_int interrupt source\n"); + break; + + } + + /* force re-evaluation of critical interrupts */ + CLR_CSE_STICKY(mpc5200.pmce); + + } + + /* second: check for main interrupt sources (hirarchical order) -> LO_int indicates peripheral sources */ + if(CHK_MSE_STICKY(pmce)) + { + + /* get source of main interrupt */ + irq = MSE_SOURCE(pmce); + + switch(irq) + { + + /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer 2 is always routed to SMI) */ + case 1: + case 2: + case 3: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + + /* add proper offset for main interrupts in the siu handler array */ + irq += BSP_MAIN_IRQ_LOWEST_OFFSET; + + /* save original mask and disable all lower priorized main interrupts*/ + crit_pri_main_mask = mpc5200.crit_pri_main_mask; + mpc5200.crit_pri_main_mask |= irqMaskTable[irq]; + + /* enable interrupt nesting */ + _CPU_MSR_GET(msr); + new_msr = msr | MSR_EE; + _CPU_MSR_SET(new_msr); + + /* call the module specific handler and pass the specific handler */ + rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle); + + /* disable interrupt nesting */ + _CPU_MSR_SET(msr); + + /* restore original interrupt mask */ + mpc5200.crit_pri_main_mask = crit_pri_main_mask; + + break; + + /* peripheral LO_int interrupt source detected */ + case 4: + + /* check for valid peripheral interrupt source */ + if(CHK_PSE_STICKY(pmce)) + { + + /* get source of peripheral interrupt */ + irq = PSE_SOURCE(pmce); + + /* add proper offset for peripheral interrupts in the siu handler array */ + irq += BSP_PER_IRQ_LOWEST_OFFSET; + + /* save original mask and disable all lower priorized main interrupts */ + per_mask = mpc5200.per_mask; + mpc5200.per_mask |= irqMaskTable[irq]; + + /* enable interrupt nesting */ + _CPU_MSR_GET(msr); + new_msr = msr | MSR_EE; + _CPU_MSR_SET(new_msr); + + /* call the module specific handler and pass the specific handler */ + rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle); + + + /* disable interrupt nesting */ + _CPU_MSR_SET(msr); + + /* restore original interrupt mask */ + mpc5200.per_mask = per_mask; + + /* force re-evaluation of peripheral interrupts */ + CLR_PSE_STICKY(mpc5200.pmce); + + } + /* this case may not occur: no valid peripheral interrupt source */ + else + { + + printk("No valid peripheral LO_int interrupt source\n"); + + } + + break; + + /* error: unknown interrupt source */ + default: + printk("Unknown peripheral LO_int interrupt source\n"); + break; + + } + + /* force re-evaluation of main interrupts */ + CLR_MSE_STICKY(mpc5200.pmce); + + } + + + /* get the content of main interrupt status register */ + pmce = mpc5200.pmce; + + } + + break; + + default: + printk("Unknown processor exception\n"); + break; + + } /* end of switch(excNum) */ + + return; + + } + + +void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx) + { + /* + * Process pending signals that have not already been + * processed by _Thread_Displatch. This happens quite + * unfrequently : the ISR must have posted an action + * to the current running thread. + */ + if ( _Thread_Do_post_task_switch_extension || + _Thread_Executing->do_post_task_switch_extension ) + { + + _Thread_Executing->do_post_task_switch_extension = FALSE; + _API_extensions_Run_postswitch(); + + } + /* + * I plan to process other thread related events here. + * This will include DEBUG session requested from keyboard... + */ +} diff --git a/c/src/lib/libbsp/powerpc/gen5200/irq/irq.h b/c/src/lib/libbsp/powerpc/gen5200/irq/irq.h new file mode 100644 index 0000000000..e0d54fdba7 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/gen5200/irq/irq.h @@ -0,0 +1,411 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC5200 BSP | ++-----------------------------------------------------------------+ +| File: irq.h ++-----------------------------------------------------------------+ +| 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.com/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains declarations for the irq controller handler | ++-----------------------------------------------------------------+ +| date history ID | +| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | +| 01.12.05 creation doe | +|*****************************************************************| +|*CVS information: | +|*(the following information is created automatically, | +|*do not edit here) | +|*****************************************************************| +|* $Log$ +|* Revision 1.6 2005/12/09 08:57:03 thomas +|* added/modifed file headers +|* +|* Revision 1.5 2005/12/06 14:11:12 thomas +|* added EB file headers +|* + * +|*****************************************************************| +\*===============================================================*/ +/***********************************************************************/ +/* */ +/* Module: irq.h */ +/* Date: 07/17/2003 */ +/* Purpose: RTEMS MPC5x00 CPU interrupt header file */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Description: This include file describe the data structure and */ +/* the functions implemented by rtems to write */ +/* interrupt handlers. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Code */ +/* References: MPC8260ads CPU interrupt header file */ +/* Module: irq.h */ +/* Project: RTEMS 4.6.0pre1 / MCF8260ads BSP */ +/* Version 1.1 */ +/* Date: 10/10/2002 */ +/* */ +/* Author(s) / Copyright(s): */ +/* */ +/* Copyright (C) 1999 valette@crf.canon.fr */ +/* */ +/* This code is heavilly inspired by the public specification of */ +/* STREAM V2 that can be found at: */ +/* */ +/* <http://www.chorus.com/Documentation/index.html> by following */ +/* the STREAM API Specification Document link. */ +/* */ +/* Modified for mpc8260 by Andy Dachs <a.dachs@sstl.co.uk> */ +/* Surrey Satellite Technology Limited */ +/* The interrupt handling on the mpc8260 seems quite different from */ +/* the 860 (I don't know the 860 well). Although some interrupts */ +/* are routed via the CPM irq and some are direct to the SIU they */ +/* all appear logically the same.Therefore I removed the distinction */ +/* between SIU and CPM interrupts. */ +/* */ +/* The license and distribution terms for this file may be */ +/* found in found in the file LICENSE in this distribution or at */ +/* http://www.OARcorp.com/rtems/license.html. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* 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 */ +/* */ +/***********************************************************************/ + +#ifndef LIBBSP_POWERPC_MPC5200_IRQ_IRQ_H +#define LIBBSP_POWERPC_MPC5200_IRQ_IRQ_H + +#define CHK_CE_SHADOW(pmce) ((pmce) & 0x00000001) +#define CHK_CSE_STICKY(pmce) (((pmce) >> 10) & 0x00000001) +#define CHK_MSE_STICKY(pmce) (((pmce) >> 21) & 0x00000001) +#define CHK_PSE_STICKY(pmce) (((pmce) >> 29) & 0x00000001) +#define CLR_CSE_STICKY(pmce) ((pmce) |= (1 << 29 )) +#define CLR_MSE_STICKY(pmce) ((pmce) |= (1 << 21 )) +#define CLR_PSE_STICKY(pmce) ((pmce) |= (1 << 10 )) +#define CSE_SOURCE(source) (((source) >> 8) & 0x00000003) +#define MSE_SOURCE(source) (((source) >> 16) & 0x0000001F) +#define PSE_SOURCE(source) (((source) >> 24) & 0x0000001F) + +/* + * Base index for the module specific irq handlers + */ +#define BSP_ASM_IRQ_VECTOR_BASE 0 +#define BSP_PER_VECTOR_BASE BSP_ASM_IRQ_VECTOR_BASE /* 0 */ +/* + * Peripheral IRQ handlers related definitions + */ +#define BSP_PER_IRQ_NUMBER 22 +#define BSP_PER_IRQ_LOWEST_OFFSET BSP_PER_VECTOR_BASE /* 0 */ +#define BSP_PER_IRQ_MAX_OFFSET BSP_PER_IRQ_LOWEST_OFFSET + BSP_PER_IRQ_NUMBER - 1 /* 21 */ +/* + * Main IRQ handlers related definitions + */ +#define BSP_MAIN_IRQ_NUMBER 17 +#define BSP_MAIN_IRQ_LOWEST_OFFSET BSP_PER_IRQ_MAX_OFFSET + 1 /* 22 */ +#define BSP_MAIN_IRQ_MAX_OFFSET BSP_MAIN_IRQ_LOWEST_OFFSET + BSP_MAIN_IRQ_NUMBER - 1 /* 38 */ +/* + * Critical IRQ handlers related definitions + */ +#define BSP_CRIT_IRQ_NUMBER 4 +#define BSP_CRIT_IRQ_LOWEST_OFFSET BSP_MAIN_IRQ_MAX_OFFSET + 1 /* 39 */ +#define BSP_CRIT_IRQ_MAX_OFFSET BSP_CRIT_IRQ_LOWEST_OFFSET + BSP_CRIT_IRQ_NUMBER - 1 /* 42 */ +/* + * Summary of SIU interrupts + */ +#define BSP_SIU_IRQ_NUMBER BSP_CRIT_IRQ_MAX_OFFSET + 1 /* 43 */ +#define BSP_SIU_IRQ_LOWEST_OFFSET BSP_PER_IRQ_LOWEST_OFFSET /* 0 */ +#define BSP_SIU_IRQ_MAX_OFFSET BSP_CRIT_IRQ_MAX_OFFSET /* 42 */ +/* + * Processor IRQ handlers related definitions + */ +#define BSP_PROCESSOR_IRQ_NUMBER 3 +#define BSP_PROCESSOR_IRQ_LOWEST_OFFSET BSP_CRIT_IRQ_MAX_OFFSET + 1 /* 44 */ +#define BSP_PROCESSOR_IRQ_MAX_OFFSET BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER - 1 /* 46 */ +/* + * Summary + */ +#define BSP_IRQ_NUMBER BSP_PROCESSOR_IRQ_MAX_OFFSET + 1 /* 47 */ +#define BSP_LOWEST_OFFSET BSP_PER_IRQ_LOWEST_OFFSET /* 0 */ +#define BSP_MAX_OFFSET BSP_PROCESSOR_IRQ_MAX_OFFSET /* 46 */ + +#ifndef ASM + +/* +extern volatile unsigned int ppc_cached_irq_mask; +*/ + +/* + * index table for the module specific handlers, a few entries are only placeholders + */ +typedef enum + { + BSP_SIU_IRQ_SMARTCOMM = BSP_PER_IRQ_LOWEST_OFFSET + 0, + BSP_SIU_IRQ_PSC1 = BSP_PER_IRQ_LOWEST_OFFSET + 1, + BSP_SIU_IRQ_PSC2 = BSP_PER_IRQ_LOWEST_OFFSET + 2, + BSP_SIU_IRQ_PSC3 = BSP_PER_IRQ_LOWEST_OFFSET + 3, + BSP_SIU_IRQ_PSC6 = BSP_PER_IRQ_LOWEST_OFFSET + 4, + BSP_SIU_IRQ_ETH = BSP_PER_IRQ_LOWEST_OFFSET + 5, + BSP_SIU_IRQ_USB = BSP_PER_IRQ_LOWEST_OFFSET + 6, + BSP_SIU_IRQ_ATA = BSP_PER_IRQ_LOWEST_OFFSET + 7, + BSP_SIU_IRQ_PCI_CRT = BSP_PER_IRQ_LOWEST_OFFSET + 8, + BSP_SIU_IRQ_PCI_SC_RX = BSP_PER_IRQ_LOWEST_OFFSET + 9, + BSP_SIU_IRQ_PCI_SC_TX = BSP_PER_IRQ_LOWEST_OFFSET + 10, + BSP_SIU_IRQ_PSC4 = BSP_PER_IRQ_LOWEST_OFFSET + 11, + BSP_SIU_IRQ_PSC5 = BSP_PER_IRQ_LOWEST_OFFSET + 12, + BSP_SIU_IRQ_SPI_MODF = BSP_PER_IRQ_LOWEST_OFFSET + 13, + BSP_SIU_IRQ_SPI_SPIF = BSP_PER_IRQ_LOWEST_OFFSET + 14, + BSP_SIU_IRQ_I2C1 = BSP_PER_IRQ_LOWEST_OFFSET + 15, + BSP_SIU_IRQ_I2C2 = BSP_PER_IRQ_LOWEST_OFFSET + 16, + BSP_SIU_IRQ_MSCAN1 = BSP_PER_IRQ_LOWEST_OFFSET + 17, + BSP_SIU_IRQ_MSCAN2 = BSP_PER_IRQ_LOWEST_OFFSET + 18, + BSP_SIU_IRQ_IR_RX = BSP_PER_IRQ_LOWEST_OFFSET + 19, + BSP_SIU_IRQ_IR_TX = BSP_PER_IRQ_LOWEST_OFFSET + 20, + BSP_SIU_IRQ_XLB_ARB = BSP_PER_IRQ_LOWEST_OFFSET + 21, + + BSP_SIU_IRQ_SL_TIMER1 = BSP_MAIN_IRQ_LOWEST_OFFSET + 0, /* handler entry only used in case of SMI */ + BSP_SIU_IRQ_IRQ1 = BSP_MAIN_IRQ_LOWEST_OFFSET + 1, + BSP_SIU_IRQ_IRQ2 = BSP_MAIN_IRQ_LOWEST_OFFSET + 2, + BSP_SIU_IRQ_IRQ3 = BSP_MAIN_IRQ_LOWEST_OFFSET + 3, + BSP_SIU_IRQ_LO_INT = BSP_MAIN_IRQ_LOWEST_OFFSET + 4, /* handler entry never used (only placeholder) */ + BSP_SIU_IRQ_RTC_PER = BSP_MAIN_IRQ_LOWEST_OFFSET + 5, + BSP_SIU_IRQ_RTC_STW = BSP_MAIN_IRQ_LOWEST_OFFSET + 6, + BSP_SIU_IRQ_GPIO_STD = BSP_MAIN_IRQ_LOWEST_OFFSET + 7, + BSP_SIU_IRQ_GPIO_WKUP = BSP_MAIN_IRQ_LOWEST_OFFSET + 8, + BSP_SIU_IRQ_TMR0 = BSP_MAIN_IRQ_LOWEST_OFFSET + 9, + BSP_SIU_IRQ_TMR1 = BSP_MAIN_IRQ_LOWEST_OFFSET + 10, + BSP_SIU_IRQ_TMR2 = BSP_MAIN_IRQ_LOWEST_OFFSET + 1, + BSP_SIU_IRQ_TMR3 = BSP_MAIN_IRQ_LOWEST_OFFSET + 12, + BSP_SIU_IRQ_TMR4 = BSP_MAIN_IRQ_LOWEST_OFFSET + 13, + BSP_SIU_IRQ_TMR5 = BSP_MAIN_IRQ_LOWEST_OFFSET + 14, + BSP_SIU_IRQ_TMR6 = BSP_MAIN_IRQ_LOWEST_OFFSET + 15, + BSP_SIU_IRQ_TMR7 = BSP_MAIN_IRQ_LOWEST_OFFSET + 16, + + BSP_SIU_IRQ_IRQ0 = BSP_CRIT_IRQ_LOWEST_OFFSET + 0, + BSP_SIU_IRQ_SL_TIMER0 = BSP_CRIT_IRQ_LOWEST_OFFSET + 1, + BSP_SIU_IRQ_HI_INT = BSP_CRIT_IRQ_LOWEST_OFFSET + 2, /* handler entry never used (only placeholder) */ + BSP_SIU_IRQ_CSS_WKUP = BSP_CRIT_IRQ_LOWEST_OFFSET + 3, + + BSP_DECREMENTER = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + 0, + BSP_SYSMGMT = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + 1, + BSP_EXT = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + 2 + + }rtems_irq_symbolic_name; + +#define BSP_CRIT_IRQ_PRIO_LEVELS 4 +/*#define BSP_PERIODIC_TIMER BSP_DECREMENTER*/ +#define BSP_PERIODIC_TIMER BSP_SIU_IRQ_TMR6 +/*#define CPM_INTERRUPT*/ + + +/* + * Type definition for RTEMS managed interrupts + */ +typedef unsigned char rtems_irq_prio; +struct __rtems_irq_connect_data__; /* forward declaratiuon */ + +typedef unsigned int rtems_irq_number; +typedef void *rtems_irq_hdl_param; +typedef void (*rtems_irq_hdl) (rtems_irq_hdl_param); +typedef void (*rtems_irq_enable) (const struct __rtems_irq_connect_data__*); +typedef void (*rtems_irq_disable) (const struct __rtems_irq_connect_data__*); +typedef int (*rtems_irq_is_enabled) (const struct __rtems_irq_connect_data__*); + +typedef struct __rtems_irq_connect_data__ { + /* + * IRQ line + */ + rtems_irq_number name; + /* + * handler. See comment on handler properties below in function prototype. + */ + rtems_irq_hdl hdl; + /* + * Handler handle to store private data + */ + rtems_irq_hdl_param handle; + /* + * function for enabling interrupts at device level (ONLY!). + * The BSP code will automatically enable it at i8259s level. + * RATIONALE : anyway such code has to exist in current driver code. + * It is usually called immediately AFTER connecting the interrupt handler. + * RTEMS may well need such a function when restoring normal interrupt + * processing after a debug session. + * + */ + rtems_irq_enable on; + /* + * function for disabling interrupts at device level (ONLY!). + * The code will disable it at i8259s level. RATIONALE : anyway + * such code has to exist for clean shutdown. It is usually called + * BEFORE disconnecting the interrupt. RTEMS may well need such + * a function when disabling normal interrupt processing for + * a debug session. May well be a NOP function. + */ + rtems_irq_disable off; + /* + * function enabling to know what interrupt may currently occur + * if someone manipulates the i8259s interrupt mask without care... + */ + rtems_irq_is_enabled isOn; + +#ifdef BSP_SHARED_HANDLER_SUPPORT + /* + * Set to -1 for vectors forced to have only 1 handler + */ + void *next_handler; +#endif + +} rtems_irq_connect_data; + +typedef struct { + /* + * size of all the table fields (*Tbl) described below. + */ + unsigned int irqNb; + /* + * Default handler used when disconnecting interrupts. + */ + rtems_irq_connect_data defaultEntry; + /* + * Table containing initials/current value. + */ + rtems_irq_connect_data* irqHdlTbl; + /* + * actual value of BSP_PER_IRQ_VECTOR_BASE... + */ + rtems_irq_symbolic_name irqBase; + /* + * software priorities associated with interrupts. + * if irqPrio [i] > intrPrio [j] it means that + * interrupt handler hdl connected for interrupt name i + * will not be interrupted by the handler connected for interrupt j + * The interrupt source will be physically masked at i8259 level. + */ + rtems_irq_prio* irqPrioTbl; +}rtems_irq_global_settings; + + + +/*-------------------------------------------------------------------------+ +| Function Prototypes. ++--------------------------------------------------------------------------*/ +/* + * ------------------------ PPC CPM Mngt Routines ------- + */ + +/* + * function to disable a particular irq. After calling + * this function, even if the device asserts the interrupt line it will + * not be propagated further to the processor + */ +int BSP_irq_disable_at_siu (const rtems_irq_symbolic_name irqLine); +/* + * function to enable a particular irq. After calling + * this function, if the device asserts the interrupt line it will + * be propagated further to the processor + */ +int BSP_irq_enable_at_siu (const rtems_irq_symbolic_name irqLine); +/* + * function to acknoledge a particular irq. After calling + * this function, if a device asserts an enabled interrupt line it will + * be propagated further to the processor. Mainly usefull for people + * writting raw handlers as this is automagically done for rtems managed + * handlers. + */ +int BSP_irq_ack_at_siu (const rtems_irq_symbolic_name irqLine); +/* + * function to check if a particular irq is enabled. After calling + */ +int BSP_irq_enabled_at_siu (const rtems_irq_symbolic_name irqLine); + + + +/* + * ------------------------ RTEMS Single Irq Handler Mngt Routines ---------------- + */ +/* + * function to connect a particular irq handler. This hanlder will NOT be called + * directly as the result of the corresponding interrupt. Instead, a RTEMS + * irq prologue will be called that will : + * + * 1) save the C scratch registers, + * 2) switch to a interrupt stack if the interrupt is not nested, + * 4) modify them to disable the current interrupt at SIU level (and may + * be others depending on software priorities) + * 5) aknowledge the SIU', + * 6) demask the processor, + * 7) call the application handler + * + * As a result the hdl function provided + * + * a) can perfectly be written is C, + * b) may also well directly call the part of the RTEMS API that can be used + * from interrupt level, + * c) It only responsible for handling the jobs that need to be done at + * the device level including (aknowledging/re-enabling the interrupt at device, + * level, getting the data,...) + * + * When returning from the function, the following will be performed by + * the RTEMS irq epilogue : + * + * 1) masks the interrupts again, + * 2) restore the original SIU interrupt masks + * 3) switch back on the orinal stack if needed, + * 4) perform rescheduling when necessary, + * 5) restore the C scratch registers... + * 6) restore initial execution flow + * + */ +int BSP_install_rtems_irq_handler (const rtems_irq_connect_data*); +/* + * function to get the current RTEMS irq handler for ptr->name. It enables to + * define hanlder chain... + */ +int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* ptr); +/* + * function to get disconnect the RTEMS irq handler for ptr->name. + * This function checks that the value given is the current one for safety reason. + * The user can use the previous function to get it. + */ +int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data*); + + +void BSP_rtems_irq_mng_init(unsigned cpuId); + +int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config); + +#endif + +#endif diff --git a/c/src/lib/libbsp/powerpc/gen5200/irq/irq_asm.S b/c/src/lib/libbsp/powerpc/gen5200/irq/irq_asm.S new file mode 100644 index 0000000000..efb2465891 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/gen5200/irq/irq_asm.S @@ -0,0 +1,445 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC5200 BSP | ++-----------------------------------------------------------------+ +| File: irq_asm.S ++-----------------------------------------------------------------+ +| 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.com/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the assembler portion of the irq handling | ++-----------------------------------------------------------------+ +| date history ID | +| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | +| 01.12.05 creation doe | +|*****************************************************************| +|*CVS information: | +|*(the following information is created automatically, | +|*do not edit here) | +|*****************************************************************| +|* $Log$ +|* Revision 1.5 2005/12/09 08:57:03 thomas +|* added/modifed file headers +|* +|* Revision 1.4 2005/12/06 14:11:12 thomas +|* added EB file headers +|* + * +|*****************************************************************| +\*===============================================================*/ +/***********************************************************************/ +/* */ +/* Module: irq_asm.S */ +/* Date: 07/17/2003 */ +/* Purpose: RTEMS assembly code for PowerPC IRQ veneers */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Description: This file contains the assembly code for the */ +/* PowerPC IRQ veneers for RTEMS. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Code */ +/* References: RTEMS assembly code for PowerPC IRQ veneers */ +/* Module: irq_asm.S */ +/* Project: RTEMS 4.6.0pre1 / MCF8260ads BSP */ +/* Version 1.2 */ +/* Date: 04/18/2002 */ +/* */ +/* Author(s) / Copyright(s): */ +/* */ +/* The license and distribution terms for this file may be */ +/* found in found in the file LICENSE in this distribution or at */ +/* http://www.OARcorp.com/rtems/license.html. */ +/* */ +/* Modified to support the MCP750. */ +/* Modifications Copyright (C) 1999 Eric Valette.valette@crf.canon.fr*/ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* 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 <bsp/vectors.h>*/ +#include "../vectors/vectors.h" +#include <rtems/score/cpuopts.h> /* for PPC_HAS_FPU */ +#include <rtems/score/cpu.h> +#include <rtems/asm.h> +#include "../include/raw_exception.h" + +#define SYNC \ + sync; \ + isync + + .text + .p2align 5 + + PUBLIC_VAR(decrementer_exception_vector_prolog_code) + +SYM (decrementer_exception_vector_prolog_code): + + /* + * let room for exception frame + */ + stwu r1, - (EXCEPTION_FRAME_END)(r1) + stw r4, GPR4_OFFSET(r1) + li r4, ASM_DEC_VECTOR + ba shared_raw_irq_code_entry + + PUBLIC_VAR (decrementer_exception_vector_prolog_code_size) + + decrementer_exception_vector_prolog_code_size = . - decrementer_exception_vector_prolog_code + + PUBLIC_VAR(external_exception_vector_prolog_code) + +SYM (external_exception_vector_prolog_code): + /* + * let room for exception frame + */ + stwu r1, - (EXCEPTION_FRAME_END)(r1) + stw r4, GPR4_OFFSET(r1) + li r4, ASM_EXT_VECTOR + ba shared_raw_irq_code_entry + + PUBLIC_VAR (external_exception_vector_prolog_code_size) + + external_exception_vector_prolog_code_size = . - external_exception_vector_prolog_code + + PUBLIC_VAR(system_management_exception_vector_prolog_code) + +SYM (system_management_exception_vector_prolog_code): + /* + * let room for exception frame + */ + stwu r1, - (EXCEPTION_FRAME_END)(r1) + stw r4, GPR4_OFFSET(r1) + li r4, ASM_SYSMGMT_VECTOR + ba shared_raw_irq_code_entry + + PUBLIC_VAR (system_management_exception_vector_prolog_code_size) + + system_management_exception_vector_prolog_code_size = . - system_management_exception_vector_prolog_code + + PUBLIC_VAR(shared_raw_irq_code_entry) + PUBLIC_VAR(C_dispatch_irq_handler) + + .p2align 5 +SYM (shared_raw_irq_code_entry): + /* + * Entry conditions : + * Registers already saved : R1, R4 + * R1 : points to a location with enough room for the + * interrupt frame + * R4 : vector number + */ + /* + * Save SRR0/SRR1 As soon As possible as it is the minimal needed + * to reenable exception processing + */ + stw r0, GPR0_OFFSET(r1) + stw r2, GPR2_OFFSET(r1) + stw r3, GPR3_OFFSET(r1) + + mfsrr0 r0 + mfsrr1 r2 + mfmsr r3 + + stw r0, SRR0_FRAME_OFFSET(r1) + stw r2, SRR1_FRAME_OFFSET(r1) + + + /* + * Enable data and instruction address translation, exception recovery + * + * also, on CPUs with FP, enable FP so that FP context can be + * saved and restored (using FP instructions) + */ +#if (PPC_HAS_FPU == 0) + ori r3, r3, MSR_RI | MSR_DR/*| MSR_IR*/ +#else + ori r3, r3, MSR_RI | MSR_DR | /*MSR_IR |*/ MSR_FP +#endif + mtmsr r3 + SYNC + + /* + * Push C scratch registers on the current stack. It may + * actually be the thread stack or the interrupt stack. + * Anyway we have to make it in order to be able to call C/C++ + * functions. Depending on the nesting interrupt level, we will + * switch to the right stack later. + */ + stw r5, GPR5_OFFSET(r1) + stw r6, GPR6_OFFSET(r1) + stw r7, GPR7_OFFSET(r1) + stw r8, GPR8_OFFSET(r1) + stw r9, GPR9_OFFSET(r1) + stw r10, GPR10_OFFSET(r1) + stw r11, GPR11_OFFSET(r1) + stw r12, GPR12_OFFSET(r1) + stw r13, GPR13_OFFSET(r1) + + mfcr r5 + mfctr r6 + mfxer r7 + mflr r8 + + stw r5, EXC_CR_OFFSET(r1) + stw r6, EXC_CTR_OFFSET(r1) + stw r7, EXC_XER_OFFSET(r1) + stw r8, EXC_LR_OFFSET(r1) + + /* + * Add some non volatile registers to store information + * that will be used when returning from C handler + */ + stw r14, GPR14_OFFSET(r1) + stw r15, GPR15_OFFSET(r1) + /* + * save current stack pointer location in R14 + */ + addi r14, r1, 0 + /* + * store part of _Thread_Dispatch_disable_level address in R15 + */ + addis r15,0, _Thread_Dispatch_disable_level@ha + /* + * Get current nesting level in R2 + */ +/* mfspr r2, SPRG0 */ + addis r6, 0, _ISR_Nest_level@ha + lwz r2, _ISR_Nest_level@l( r6 ) + + /* + * Check if stack switch is necessary + */ + cmpwi r2,0 + bne nested + mfspr r1, SPRG1 + +nested: + /* + * Start Incrementing nesting level in R2 + */ + addi r2,r2,1 + + addis r6, 0, _ISR_Nest_level@ha + stw r2, _ISR_Nest_level@l( r6 ) + + /* + * Start Incrementing _Thread_Dispatch_disable_level R4 = _Thread_Dispatch_disable_level + */ + lwz r6,_Thread_Dispatch_disable_level@l(r15) + /* + * store new nesting level in SPRG0 + */ +/* mtspr SPRG0, r2 */ + + addi r6, r6, 1 + mfmsr r5 + /* + * store new _Thread_Dispatch_disable_level value + */ + stw r6, _Thread_Dispatch_disable_level@l(r15) + /* + * We are now running on the interrupt stack. External and decrementer + * exceptions are still disabled. I see no purpose trying to optimize + * further assembler code. + */ + /* + * Call C exception handler for decrementer Interrupt frame is passed just + * in case... + */ + addi r3, r14, 0x8 + bl C_dispatch_irq_handler /* C_dispatch_irq_handler(cpu_interrupt_frame* r3, vector r4) */ + /* + * start decrementing nesting level. Note : do not test result against 0 + * value as an easy exit condition because if interrupt nesting level > 1 + * then _Thread_Dispatch_disable_level > 1 + */ +/* mfspr r2, SPRG0 */ + + addis r6, 0, _ISR_Nest_level@ha + lwz r2, _ISR_Nest_level@l( r6 ) + + /* + * start decrementing _Thread_Dispatch_disable_level + */ + lwz r3,_Thread_Dispatch_disable_level@l(r15) + addi r2, r2, -1 /* Continue decrementing nesting level */ + addi r3, r3, -1 /* Continue decrementing _Thread_Dispatch_disable_level */ + + stw r2, _ISR_Nest_level@l( r6 ) +/* mtspr SPRG0, r2 */ /* End decrementing nesting level */ + + stw r3,_Thread_Dispatch_disable_level@l(r15) /* End decrementing _Thread_Dispatch_disable_level */ + cmpwi r3, 0 + /* + * switch back to original stack (done here just optimize registers + * contention. Could have been done before...) + */ + addi r1, r14, 0 + bne easy_exit /* if (_Thread_Dispatch_disable_level != 0) goto easy_exit */ + /* + * Here we are running again on the thread system stack. + * We have interrupt nesting level = _Thread_Dispatch_disable_level = 0. + * Interrupt are still disabled. Time to check if scheduler request to + * do something with the current thread... + */ + addis r4, 0, _Context_Switch_necessary@ha + lwz r5, _Context_Switch_necessary@l(r4) + cmpwi r5, 0 + bne switch + + addis r6, 0, _ISR_Signals_to_thread_executing@ha + lwz r7, _ISR_Signals_to_thread_executing@l(r6) + cmpwi r7, 0 + li r8, 0 + beq easy_exit + stw r8, _ISR_Signals_to_thread_executing@l(r6) + /* + * going to call _ThreadProcessSignalsFromIrq + * Push a complete exception like frame... + */ + stmw r16, GPR16_OFFSET(r1) + addi r3, r1, 0x8 + /* + * compute SP at exception entry + */ + addi r2, r1, EXCEPTION_FRAME_END + /* + * store it at the right place + */ + stw r2, GPR1_OFFSET(r1) + /* + * Call High Level signal handling code + */ + bl _ThreadProcessSignalsFromIrq + + + /* + * start restoring exception like frame + */ + lwz r31, EXC_CTR_OFFSET(r1) + lwz r30, EXC_XER_OFFSET(r1) + lwz r29, EXC_CR_OFFSET(r1) + lwz r28, EXC_LR_OFFSET(r1) + + mtctr r31 + mtxer r30 + mtcr r29 + mtlr r28 + + + lmw r4, GPR4_OFFSET(r1) + + + lwz r2, GPR2_OFFSET(r1) + lwz r0, GPR0_OFFSET(r1) + + /* + * Disable data and instruction translation. Make path non recoverable... + */ + mfmsr r3 + xori r3, r3, MSR_RI | MSR_DR/*| MSR_IR */ + mtmsr r3 + SYNC + /* + * Restore rfi related settings + */ + + lwz r3, SRR1_FRAME_OFFSET(r1) + mtsrr1 r3 + lwz r3, SRR0_FRAME_OFFSET(r1) + mtsrr0 r3 + + lwz r3, GPR3_OFFSET(r1) + addi r1,r1, EXCEPTION_FRAME_END + SYNC + rfi + +switch: + bl SYM (_Thread_Dispatch) + +easy_exit: + /* + * start restoring interrupt frame + */ + lwz r3, EXC_CTR_OFFSET(r1) + lwz r4, EXC_XER_OFFSET(r1) + lwz r5, EXC_CR_OFFSET(r1) + lwz r6, EXC_LR_OFFSET(r1) + + mtctr r3 + mtxer r4 + mtcr r5 + mtlr r6 + + lwz r15, GPR15_OFFSET(r1) + lwz r14, GPR14_OFFSET(r1) + lwz r13, GPR13_OFFSET(r1) + lwz r12, GPR12_OFFSET(r1) + lwz r11, GPR11_OFFSET(r1) + lwz r10, GPR10_OFFSET(r1) + lwz r9, GPR9_OFFSET(r1) + lwz r8, GPR8_OFFSET(r1) + lwz r7, GPR7_OFFSET(r1) + lwz r6, GPR6_OFFSET(r1) + lwz r5, GPR5_OFFSET(r1) + + /* + * Disable nested exception processing, data and instruction + * translation. + */ + mfmsr r3 + xori r3, r3, MSR_RI | MSR_DR/*| MSR_IR */ + mtmsr r3 + SYNC + + /* + * Restore rfi related settings + */ + + lwz r4, SRR1_FRAME_OFFSET(r1) + lwz r2, SRR0_FRAME_OFFSET(r1) + lwz r3, GPR3_OFFSET(r1) + lwz r0, GPR0_OFFSET(r1) + + mtsrr1 r4 + mtsrr0 r2 + lwz r4, GPR4_OFFSET(r1) + lwz r2, GPR2_OFFSET(r1) + addi r1,r1, EXCEPTION_FRAME_END + SYNC + rfi + diff --git a/c/src/lib/libbsp/powerpc/gen5200/irq/irq_init.c b/c/src/lib/libbsp/powerpc/gen5200/irq/irq_init.c new file mode 100644 index 0000000000..87f57626ac --- /dev/null +++ b/c/src/lib/libbsp/powerpc/gen5200/irq/irq_init.c @@ -0,0 +1,327 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC5200 BSP | ++-----------------------------------------------------------------+ +| File: irq_init.c ++-----------------------------------------------------------------+ +| 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.com/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the IRQ controller/system initialization | ++-----------------------------------------------------------------+ +| date history ID | +| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | +| 01.12.05 creation doe | +|*****************************************************************| +|*CVS information: | +|*(the following information is created automatically, | +|*do not edit here) | +|*****************************************************************| +|* $Log$ +|* Revision 1.6 2005/12/09 08:57:03 thomas +|* added/modifed file headers +|* +|* Revision 1.5 2005/12/06 14:30:42 thomas +|* updated name for peripheral register block +|* +|* Revision 1.4 2005/12/06 14:11:12 thomas +|* added EB file headers +|* + * +|*****************************************************************| +\*===============================================================*/ +/***********************************************************************/ +/* */ +/* Module: irq_init.c */ +/* Date: 07/17/2003 */ +/* Purpose: RTEMS MPC5x00 CPU interrupt initialization */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Description: This file contains the implementation of rtems */ +/* initialization related to interrupt handling. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Code */ +/* References: MBX8xx CPU interrupt initialization */ +/* Module: irq_init.c */ +/* Project: RTEMS 4.6.0pre1 / MBX8xx BSP */ +/* Version 1.1 */ +/* Date: 04/06/2001 */ +/* */ +/* Author(s) / Copyright(s): */ +/* */ +/* CopyRight (C) 2001 valette@crf.canon.fr */ +/* */ +/* The license and distribution terms for this file may be */ +/* found in found in the file LICENSE in this distribution or at */ +/* http://www.OARcorp.com/rtems/license.html. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* 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 "../include/bsp.h"*/ +#include "../include/bsp.h" +#include <rtems.h> +/*#include "../irq/irq.h"*/ +#include "../irq/irq.h" +#include <rtems/bspIo.h> +#include "../include/raw_exception.h" +#include "../include/mpc5200.h" + +extern unsigned int external_exception_vector_prolog_code_size; +extern void external_exception_vector_prolog_code(); +extern unsigned int decrementer_exception_vector_prolog_code_size; +extern void decrementer_exception_vector_prolog_code(); +extern unsigned int system_management_exception_vector_prolog_code_size; +extern void system_management_exception_vector_prolog_code(); + +extern void BSP_panic(char *s); +extern void _BSP_Fatal_error(unsigned int v); +/* +volatile unsigned int ppc_cached_irq_mask; +*/ + +/* + * default on/off function + */ +static void nop_func(){} +/* + * default isOn function + */ +static int not_connected() {return 0;} +/* + * default possible isOn function + */ +static int connected() {return 1;} + +static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER]; +static rtems_irq_global_settings initial_config; + +static rtems_irq_connect_data defaultIrq = + { + /* vectorIdex, hdl , param, on , off , isOn */ + 0, nop_func, NULL , nop_func, nop_func, not_connected }; + +static rtems_irq_prio 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 */ + }; + +uint32_t irqMaskTable[BSP_PER_IRQ_NUMBER + BSP_MAIN_IRQ_NUMBER]; + + +/* + * setup irqMaskTable to support a priorized/nested interrupt environment + */ +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 + */ +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(); + + } + +void BSP_rtems_irq_mng_init(unsigned cpuId) + { + rtems_raw_except_connect_data vectorDesc; + int i; + + BSP_SIU_irq_init(); + /* + * Initialize Rtems management interrupt table + */ + /* + * re-init the rtemsIrq table + */ + for (i = 0; i < BSP_IRQ_NUMBER; i++) + { + rtemsIrq[i] = defaultIrq; + rtemsIrq[i].name = i; + } + /* + * Init initial Interrupt management config + */ + initial_config.irqNb = BSP_IRQ_NUMBER; + initial_config.defaultEntry = defaultIrq; + initial_config.irqHdlTbl = rtemsIrq; + initial_config.irqBase = BSP_ASM_IRQ_VECTOR_BASE; + initial_config.irqPrioTbl = irqPrioTable; + + if (!BSP_rtems_irq_mngt_set(&initial_config)) + { + /* + * put something here that will show the failure... + */ + BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); + } + + /* + * We must connect the raw irq handler for the two + * expected interrupt sources : decrementer and external interrupts. + */ + vectorDesc.exceptIndex = ASM_DEC_VECTOR; + vectorDesc.hdl.vector = ASM_DEC_VECTOR; + vectorDesc.hdl.raw_hdl = decrementer_exception_vector_prolog_code; + vectorDesc.hdl.raw_hdl_size = (unsigned) &decrementer_exception_vector_prolog_code_size; + vectorDesc.on = nop_func; + vectorDesc.off = nop_func; + vectorDesc.isOn = connected; + + if (!mpc60x_set_exception (&vectorDesc)) + { + BSP_panic("Unable to initialize RTEMS decrementer raw exception\n"); + } + + vectorDesc.exceptIndex = ASM_EXT_VECTOR; + vectorDesc.hdl.vector = ASM_EXT_VECTOR; + vectorDesc.hdl.raw_hdl = external_exception_vector_prolog_code; + vectorDesc.hdl.raw_hdl_size = (unsigned) &external_exception_vector_prolog_code_size; + + if (!mpc60x_set_exception (&vectorDesc)) + { + BSP_panic("Unable to initialize RTEMS external raw exception\n"); + } + + vectorDesc.exceptIndex = ASM_SYSMGMT_VECTOR; + vectorDesc.hdl.vector = ASM_SYSMGMT_VECTOR; + vectorDesc.hdl.raw_hdl = system_management_exception_vector_prolog_code; + vectorDesc.hdl.raw_hdl_size = (unsigned) &system_management_exception_vector_prolog_code_size; + + if (!mpc60x_set_exception (&vectorDesc)) + { + BSP_panic("Unable to initialize RTEMS system management raw exception\n"); + } + +} + |