diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2011-06-17 11:58:41 +0000 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2011-06-17 11:58:41 +0000 |
commit | 25ed11d08e98b9893a076c57f694c14892155c01 (patch) | |
tree | 9dfff040a25548e21b1518f66612a33b6d82fa3d /c/src/lib/libbsp/powerpc/gen5200/irq/irq.c | |
parent | 2011-06-17 Ralf Corsépius <ralf.corsepius@rtems.org> (diff) | |
download | rtems-25ed11d08e98b9893a076c57f694c14892155c01.tar.bz2 |
2011-06-17 Sebastian Huber <sebastian.huber@embedded-brains.de>
* Makefile.am: Added custom memcpy(). Update for network sources.
* configure.ac: Enable interrupt driven Termios for all BSPs.
* ide/pcmcia_ide.c: Disable broken DMA support.
* include/bsp.h: Fixed NEED_LOW_LEVEL_INIT define. Set default
console baud to 115200.
* include/irq.h, irq/irq.c: Fixed interrupt handling to avoid the
following problems: 1. multiple invokation of peripheral interrupt
handlers, 2. missing synchronization after mask write and enabling of
external exceptions, and 3. logic overhead.
* network_5200/network.c: Added MII interface. Fixed controller
restart after FIFO errors. Performance improvements.
* start/start.S: Fixed ROM startup. Initialize XLB arbiter for all
BSPs.
* startup/bspstart.c: Special intialization for MPC5200B (B variant).
Install standard alignment handler.
* startup/cpuinit.c, startup/linkcmds.brs5l, startup/linkcmds.dp2,
startup/linkcmds.icecube, startup/linkcmds.pm520_cr825,
startup/linkcmds.pm520_ze30: Avoid accesses outside the RAM area.
Diffstat (limited to '')
-rw-r--r-- | c/src/lib/libbsp/powerpc/gen5200/irq/irq.c | 239 |
1 files changed, 86 insertions, 153 deletions
diff --git a/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c b/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c index 27e3c09856..c76ce5a12d 100644 --- a/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c +++ b/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c @@ -171,10 +171,6 @@ static inline void BSP_enable_per_irq_at_siu( uint8_t lo_hi_ind = 0, prio_index_offset; uint32_t *reg; - 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; @@ -223,11 +219,11 @@ static inline void BSP_enable_per_irq_at_siu( /* 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; - + /* 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( @@ -484,15 +480,15 @@ 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 - uint32_t mask = *maskreg; - irq += offset; - *maskreg = mask | irqMaskTable [irq]; - #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 @@ -500,9 +496,8 @@ static void dispatch(uint32_t irq, uint32_t offset, volatile uint32_t *maskreg) #if (ALLOW_IRQ_NESTING == 1) ppc_external_exceptions_disable(msr); + *maskreg = mask; #endif - - *maskreg = mask; } /* @@ -526,151 +521,92 @@ int C_dispatch_irq_handler(BSP_Exception_frame *frame, unsigned excNum) printk( "not counting %d\n", excNum); #endif - switch (excNum) { - /* - * Handle decrementer interrupt - */ - case ASM_DEC_VECTOR: + /* get the content of main interrupt status register */ + pmce = mpc5200.pmce; - /* Dispatch interrupt handlers */ - bsp_interrupt_handler_dispatch( BSP_DECREMENTER); + /* 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; - break; + /* irq0, slice timer 1 or ccs wakeup detected */ + case 0: + case 1: + case 3: - case ASM_EXT_VECTOR: - case ASM_60X_SYSMGMT_VECTOR: - /* get the content of main interrupt status register */ - pmce = mpc5200.pmce; + /* add proper offset for critical interrupts in the siu + * handler array */ + irq += BSP_CRIT_IRQ_LOWEST_OFFSET; - /* 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 (hierarchical 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; - - /* Dispatch interrupt handlers */ - bsp_interrupt_handler_dispatch( irq); - - 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); - - dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask); - - /* force re-evaluation of peripheral interrupts */ - CLR_PSE_STICKY( mpc5200.pmce); - } else { - /* this case may not occur: no valid peripheral - * interrupt source */ - printk( "No valid peripheral HI_int interrupt source\n"); - } - break; - default: - /* error: unknown interrupt source */ - 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 (hierarchical 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: - 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: - dispatch(irq, BSP_MAIN_IRQ_LOWEST_OFFSET, &mpc5200.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); - - dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask); - - /* force re-evaluation of peripheral interrupts */ - CLR_PSE_STICKY( mpc5200.pmce); - } else { - /* this case may not occur: no valid peripheral - * interrupt source */ - 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); - } - - if (CHK_PSE_STICKY( pmce)) { - /* get source of peripheral interrupt */ - irq = PSE_SOURCE( pmce); + /* Dispatch interrupt handlers */ + bsp_interrupt_handler_dispatch( irq); - dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask); + break; - /* force re-evaluation of peripheral interrupts */ - CLR_PSE_STICKY( mpc5200.pmce); - } + default: + /* error: unknown interrupt source */ + printk( "Unknown HI_int interrupt source\n"); + break; + } + } - /* get the content of main interrupt status register */ - pmce = mpc5200.pmce; + /* 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"); } - break; + } - default: - printk( "Unknown processor exception\n"); - break; + /* force re-evaluation of interrupts */ + mpc5200.pmce = PMCE_CSE_STICKY | PMCE_MSE_STICKY | PMCE_PSE_STICKY; - } /* end of switch( excNum) */ + /* get the content of main interrupt status register */ + pmce = mpc5200.pmce; + } #if (BENCHMARK_IRQ_PROCESSING == 1) stop = PPC_Get_timebase_register(); @@ -771,9 +707,6 @@ rtems_status_code bsp_interrupt_facility_initialize( void) if (ppc_exc_set_handler( ASM_EXT_VECTOR, C_dispatch_irq_handler)) { return RTEMS_IO_ERROR; } - if (ppc_exc_set_handler( ASM_DEC_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; } |