diff options
author | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2007-07-10 16:00:28 +0000 |
---|---|---|
committer | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2007-07-10 16:00:28 +0000 |
commit | f610e83f5350e09d29a23352b420551d06f15499 (patch) | |
tree | 6f1914643c458af3c680a057405dea6bd0c7400a /c/src/lib/libbsp/powerpc/gen83xx/irq | |
parent | 2007-07-06 Joel Sherrill <joel.sherrill@OARcorp.com> (diff) | |
download | rtems-f610e83f5350e09d29a23352b420551d06f15499.tar.bz2 |
compilable release of virtex/gen83xx/gen5200 powerpc adaptations. Merged many different versions of new exception handling code to shared sources.
Diffstat (limited to 'c/src/lib/libbsp/powerpc/gen83xx/irq')
-rw-r--r-- | c/src/lib/libbsp/powerpc/gen83xx/irq/ipic.c | 394 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/gen83xx/irq/irq.h | 149 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/gen83xx/irq/irq_init.c | 413 |
3 files changed, 956 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/gen83xx/irq/ipic.c b/c/src/lib/libbsp/powerpc/gen83xx/irq/ipic.c new file mode 100644 index 0000000000..8433c32a67 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/gen83xx/irq/ipic.c @@ -0,0 +1,394 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC83xx BSP | ++-----------------------------------------------------------------+ +| Copyright (c) 2007 | +| 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 integrates the IPIC irq controller | +\*===============================================================*/ + +#include <mpc83xx/mpc83xx.h> +#include <rtems.h> +#include <rtems/bspIo.h> +#include <bsp.h> +#include <bsp/irq.h> +#include <rtems/powerpc/powerpc.h> + +typedef struct { + volatile uint32_t *pend_reg; + volatile uint32_t *mask_reg; + const uint32_t bit_num; +} BSP_isrc_rsc_t; + +const BSP_isrc_rsc_t BSP_ipic_isrc_rsc[] = { + /* vector 0 */ + {&mpc83xx.ipic.sersr,&mpc83xx.ipic.sermr,31}, + {NULL,NULL,0}, + {NULL,NULL,0}, + {NULL,NULL,0}, + {NULL,NULL,0}, + {NULL,NULL,0}, + {NULL,NULL,0}, + {NULL,NULL,0}, + /* vector 8 */ + {NULL,NULL,0}, /* reserved vector 8 */ + /* vector 9: UART1 SIxxR_H, Bit 24 */ + {&mpc83xx.ipic.sipnr[0],&mpc83xx.ipic.simsr[0],24}, + /* vector 10: UART2 SIxxR_H, Bit 25 */ + {&mpc83xx.ipic.sipnr[0],&mpc83xx.ipic.simsr[0],25}, + /* vector 11: SEC SIxxR_H, Bit 26 */ + {&mpc83xx.ipic.sipnr[0],&mpc83xx.ipic.simsr[0],26}, + {NULL,NULL,0}, /* reserved vector 12 */ + {NULL,NULL,0}, /* reserved vector 13 */ + /* vector 14: I2C1 SIxxR_H, Bit 29 */ + {&mpc83xx.ipic.sipnr[0],&mpc83xx.ipic.simsr[0],29}, + /* vector 15: I2C2 SIxxR_H, Bit 30 */ + {&mpc83xx.ipic.sipnr[0],&mpc83xx.ipic.simsr[0],30}, + /* vector 16: SPI SIxxR_H, Bit 31 */ + {&mpc83xx.ipic.sipnr[0],&mpc83xx.ipic.simsr[0],31}, + /* vector 17: IRQ1 SExxR , Bit 1 */ + {&mpc83xx.ipic.sepnr ,&mpc83xx.ipic.semsr , 1}, + /* vector 18: IRQ2 SExxR , Bit 2 */ + {&mpc83xx.ipic.sepnr ,&mpc83xx.ipic.semsr , 2}, + /* vector 19: IRQ3 SExxR , Bit 3 */ + {&mpc83xx.ipic.sepnr ,&mpc83xx.ipic.semsr , 3}, + /* vector 20: IRQ4 SExxR , Bit 4 */ + {&mpc83xx.ipic.sepnr ,&mpc83xx.ipic.semsr , 4}, + /* vector 21: IRQ5 SExxR , Bit 5 */ + {&mpc83xx.ipic.sepnr ,&mpc83xx.ipic.semsr , 5}, + /* vector 22: IRQ6 SExxR , Bit 6 */ + {&mpc83xx.ipic.sepnr ,&mpc83xx.ipic.semsr , 6}, + /* vector 23: IRQ7 SExxR , Bit 7 */ + {&mpc83xx.ipic.sepnr ,&mpc83xx.ipic.semsr , 7}, + {NULL,NULL,0}, /* reserved vector 24 */ + {NULL,NULL,0}, /* reserved vector 25 */ + {NULL,NULL,0}, /* reserved vector 26 */ + {NULL,NULL,0}, /* reserved vector 27 */ + {NULL,NULL,0}, /* reserved vector 28 */ + {NULL,NULL,0}, /* reserved vector 29 */ + {NULL,NULL,0}, /* reserved vector 30 */ + {NULL,NULL,0}, /* reserved vector 31 */ + /* vector 32: TSEC1 Tx SIxxR_H , Bit 0 */ + {&mpc83xx.ipic.sipnr[0],&mpc83xx.ipic.simsr[0], 0}, + /* vector 33: TSEC1 Rx SIxxR_H , Bit 1 */ + {&mpc83xx.ipic.sipnr[0],&mpc83xx.ipic.simsr[0], 1}, + /* vector 34: TSEC1 Err SIxxR_H , Bit 2 */ + {&mpc83xx.ipic.sipnr[0],&mpc83xx.ipic.simsr[0], 2}, + /* vector 35: TSEC2 Tx SIxxR_H , Bit 3 */ + {&mpc83xx.ipic.sipnr[0],&mpc83xx.ipic.simsr[0], 3}, + /* vector 36: TSEC2 Rx SIxxR_H , Bit 4 */ + {&mpc83xx.ipic.sipnr[0],&mpc83xx.ipic.simsr[0], 4}, + /* vector 37: TSEC2 Err SIxxR_H , Bit 5 */ + {&mpc83xx.ipic.sipnr[0],&mpc83xx.ipic.simsr[0], 5}, + /* vector 38: USB DR SIxxR_H , Bit 6 */ + {&mpc83xx.ipic.sipnr[0],&mpc83xx.ipic.simsr[0], 6}, + /* vector 39: USB MPH SIxxR_H , Bit 7 */ + {&mpc83xx.ipic.sipnr[0],&mpc83xx.ipic.simsr[0], 7}, + {NULL,NULL,0}, /* reserved vector 40 */ + {NULL,NULL,0}, /* reserved vector 41 */ + {NULL,NULL,0}, /* reserved vector 42 */ + {NULL,NULL,0}, /* reserved vector 43 */ + {NULL,NULL,0}, /* reserved vector 44 */ + {NULL,NULL,0}, /* reserved vector 45 */ + {NULL,NULL,0}, /* reserved vector 46 */ + {NULL,NULL,0}, /* reserved vector 47 */ + /* vector 48: IRQ0 SExxR , Bit 0 */ + {&mpc83xx.ipic.sepnr ,&mpc83xx.ipic.semsr , 0}, + {NULL,NULL,0}, /* reserved vector 49 */ + {NULL,NULL,0}, /* reserved vector 50 */ + {NULL,NULL,0}, /* reserved vector 51 */ + {NULL,NULL,0}, /* reserved vector 52 */ + {NULL,NULL,0}, /* reserved vector 53 */ + {NULL,NULL,0}, /* reserved vector 54 */ + {NULL,NULL,0}, /* reserved vector 55 */ + {NULL,NULL,0}, /* reserved vector 56 */ + {NULL,NULL,0}, /* reserved vector 57 */ + {NULL,NULL,0}, /* reserved vector 58 */ + {NULL,NULL,0}, /* reserved vector 59 */ + {NULL,NULL,0}, /* reserved vector 60 */ + {NULL,NULL,0}, /* reserved vector 61 */ + {NULL,NULL,0}, /* reserved vector 62 */ + {NULL,NULL,0}, /* reserved vector 63 */ + /* vector 64: RTC SEC SIxxR_L , Bit 0 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1], 0}, + /* vector 65: PIT SIxxR_L , Bit 1 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1], 1}, + /* vector 66: PCI1 SIxxR_L , Bit 2 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1], 2}, + /* vector 67: PCI2 SIxxR_L , Bit 3 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1], 3}, + /* vector 68: RTC ALR SIxxR_L , Bit 4 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1], 4}, + /* vector 69: MU SIxxR_L , Bit 5 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1], 5}, + /* vector 70: SBA SIxxR_L , Bit 6 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1], 6}, + /* vector 71: DMA SIxxR_L , Bit 7 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1], 7}, + /* vector 72: GTM4 SIxxR_L , Bit 8 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1], 8}, + /* vector 73: GTM8 SIxxR_L , Bit 9 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1], 9}, + /* vector 74: GPIO1 SIxxR_L , Bit 10 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1],10}, + /* vector 75: GPIO2 SIxxR_L , Bit 11 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1],11}, + /* vector 76: DDR SIxxR_L , Bit 12 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1],12}, + /* vector 77: LBC SIxxR_L , Bit 13 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1],13}, + /* vector 78: GTM2 SIxxR_L , Bit 14 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1],14}, + /* vector 79: GTM6 SIxxR_L , Bit 15 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1],15}, + /* vector 80: PMC SIxxR_L , Bit 16 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1],16}, + {NULL,NULL,0}, /* reserved vector 81 */ + {NULL,NULL,0}, /* reserved vector 82 */ + {NULL,NULL,0}, /* reserved vector 63 */ + /* vector 84: GTM3 SIxxR_L , Bit 20 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1],20}, + /* vector 85: GTM7 SIxxR_L , Bit 21 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1],21}, + {NULL,NULL,0}, /* reserved vector 81 */ + {NULL,NULL,0}, /* reserved vector 82 */ + {NULL,NULL,0}, /* reserved vector 63 */ + {NULL,NULL,0}, /* reserved vector 63 */ + /* vector 90: GTM1 SIxxR_L , Bit 26 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1],26}, + /* vector 91: GTM5 SIxxR_L , Bit 27 */ + {&mpc83xx.ipic.sipnr[1],&mpc83xx.ipic.simsr[1],27} +}; + +/* + * data structure to handle all mask registers in the IPIC + */ +typedef struct { + uint32_t simsr_mask[2]; + uint32_t semsr_mask; + uint32_t sermr_mask; +} BSP_ipic_mask_t; + +/* + * this array will be filled with mask values needed + * to temporarily disable all IRQ soures with lower or same + * priority of the current source (whose vector is the array index) + */ +BSP_ipic_mask_t BSP_ipic_prio2mask[BSP_ARRAY_CNT(BSP_ipic_isrc_rsc)]; + + +/* + * functions to enable/disable a source at the ipic + */ +void BSP_irq_enable_at_ipic (rtems_irq_number irqnum) +{ + uint32_t vecnum = irqnum - BSP_IPIC_IRQ_LOWEST_OFFSET; + const BSP_isrc_rsc_t *rsc_ptr; + + if ((vecnum >= 0) + && (vecnum < BSP_ARRAY_CNT(BSP_ipic_isrc_rsc))) { + rsc_ptr = &BSP_ipic_isrc_rsc[vecnum]; + if (rsc_ptr->mask_reg != NULL) { + *(rsc_ptr->mask_reg) |= 1 << (31-rsc_ptr->bit_num); + } + } +} + +void BSP_irq_disable_at_ipic (rtems_irq_number irqnum) +{ + uint32_t vecnum = irqnum - BSP_IPIC_IRQ_LOWEST_OFFSET; + const BSP_isrc_rsc_t *rsc_ptr; + + if ((vecnum >= 0) + && (vecnum < BSP_ARRAY_CNT(BSP_ipic_isrc_rsc))) { + rsc_ptr = &BSP_ipic_isrc_rsc[vecnum]; + if (rsc_ptr->mask_reg != NULL) { + *(rsc_ptr->mask_reg) &= ~(1 << (31-rsc_ptr->bit_num)); + } + } +} + + +/* + * IRQ Handler: this is called from the primary exception dispatcher + */ +rtems_status_code BSP_irq_handle_at_ipic(uint32_t excNum) +{ + rtems_status_code rc = RTEMS_SUCCESSFUL; + rtems_irq_connect_data *tbl_entry; + int32_t vecnum; + uint32_t msr_value; + uint32_t msr_save; + uint32_t msr_enable = 0; + BSP_ipic_mask_t mask_save; + const BSP_ipic_mask_t *mask_ptr; + /* + * get vector + */ + switch(excNum) { + case ASM_EXT_VECTOR: + vecnum = MPC83xx_VCR_TO_VEC(mpc83xx.ipic.sivcr); + msr_enable = PPC_MSR_EE; + break; + case ASM_SYSMGMT_VECTOR: + vecnum = MPC83xx_VCR_TO_VEC(mpc83xx.ipic.smvcr); + msr_enable = PPC_MSR_EE; + break; +#if defined(ASM_CRIT_VECTOR) + case ASM_CRIT_VECTOR: + vecnum = MPC83xx_VCR_TO_VEC(mpc83xx.ipic.scvcr); + break; +#endif + default: + vecnum = -1; + } + /* + * check vector number + */ + if ((vecnum >= 0) + && (vecnum < BSP_ARRAY_CNT(BSP_ipic_isrc_rsc))) { + /* + * save current mask registers + */ + mask_save.simsr_mask[0] = mpc83xx.ipic.simsr[0]; + mask_save.simsr_mask[1] = mpc83xx.ipic.simsr[1]; + mask_save.semsr_mask = mpc83xx.ipic.semsr ; + mask_save.sermr_mask = mpc83xx.ipic.sermr ; + /* + * mask all lower prio interrupts + */ + mask_ptr = &BSP_ipic_prio2mask[vecnum]; + mpc83xx.ipic.simsr[0] &= mask_ptr->simsr_mask[0]; + mpc83xx.ipic.simsr[1] &= mask_ptr->simsr_mask[1]; + mpc83xx.ipic.semsr &= mask_ptr->semsr_mask ; + mpc83xx.ipic.sermr &= mask_ptr->sermr_mask ; + /* + * reenable msr_ee + */ + _CPU_MSR_GET(msr_value); + msr_save = msr_value; + msr_value |= msr_enable; + _CPU_MSR_SET(msr_value); + /* + * call handler + */ + tbl_entry = &BSP_rtems_irq_tbl[vecnum+BSP_IPIC_IRQ_LOWEST_OFFSET]; + if (tbl_entry->hdl != NULL) { + (tbl_entry->hdl) (tbl_entry->handle); + } else { + printk("IPIC: Spurious interrupt; excNum=0x%x, vector=0x%02x\n\r", + excNum,vecnum); + } + /* + * disable msr_enable + */ + _CPU_MSR_SET(msr_save); + /* + * restore initial masks + */ + mpc83xx.ipic.simsr[0] = mask_save.simsr_mask[0]; + mpc83xx.ipic.simsr[1] = mask_save.simsr_mask[1]; + mpc83xx.ipic.semsr = mask_save.semsr_mask ; + mpc83xx.ipic.sermr = mask_save.sermr_mask ; + } + return rc; +} + + +/* + * fill the array BSP_ipic_prio2mask to allow masking of lower prio sources + * to implement nested interrupts + */ +rtems_status_code BSP_ipic_calc_prio2mask(void) +{ + rtems_status_code rc = RTEMS_SUCCESSFUL; + /* + * FIXME: fill the array + */ + return rc; +} + +/* + * activate the interrupt controller + */ +rtems_status_code BSP_ipic_intc_init(void) +{ + uint32_t msr_value; + rtems_status_code rc = RTEMS_SUCCESSFUL; + + /* + * mask off all interrupts + */ + mpc83xx.ipic.simsr[0] = 0; + mpc83xx.ipic.simsr[1] = 0; + mpc83xx.ipic.semsr = 0; + mpc83xx.ipic.sermr = 0; + /* + * set desired configuration as defined in bspopts.h + * normally, the default values should be fine + */ +#if defined(BSP_SICFR_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.sicfr = BSP_SICFR_VAL; +#endif + + /* + * set desired priorities as defined in bspopts.h + * normally, the default values should be fine + */ +#if defined(BSP_SIPRR0_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.siprr[0] = BSP_SIPRR0_VAL; +#endif + +#if defined(BSP_SIPRR1_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.siprr[1] = BSP_SIPRR1_VAL; +#endif + +#if defined(BSP_SIPRR2_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.siprr[2] = BSP_SIPRR2_VAL; +#endif + +#if defined(BSP_SIPRR3_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.siprr[3] = BSP_SIPRR3_VAL; +#endif + +#if defined(BSP_SMPRR0_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.smprr[0] = BSP_SMPRR0_VAL; +#endif + +#if defined(BSP_SMPRR1_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.smprr[1] = BSP_SMPRR1_VAL; +#endif + +#if defined(BSP_SECNR_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.secnr = BSP_SECNR_VAL; +#endif + + /* + * calculate priority masks + */ + rc = BSP_ipic_calc_prio2mask(); + if (rc == RTEMS_SUCCESSFUL) { + /* + * enable (non-critical) exceptions + */ + + _CPU_MSR_GET(msr_value); + msr_value |= PPC_MSR_EE; + _CPU_MSR_SET(msr_value); + + /* install exit handler to close ipic when program atexit called */ + /* atexit(ipic_intc_exit); */ + } + return rc; +} + diff --git a/c/src/lib/libbsp/powerpc/gen83xx/irq/irq.h b/c/src/lib/libbsp/powerpc/gen83xx/irq/irq.h new file mode 100644 index 0000000000..b9d3cfe49e --- /dev/null +++ b/c/src/lib/libbsp/powerpc/gen83xx/irq/irq.h @@ -0,0 +1,149 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC83xx BSP | ++-----------------------------------------------------------------+ +| Copyright (c) 2007 | +| 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 declares constants of the interrupt controller | +\*===============================================================*/ +#ifndef GEN83xx_IRQ_IRQ_H +#define GEN83xx_IRQ_IRQ_H + +#include <rtems.h> +#include <rtems/irq.h> + +/* + * the following definitions specify the indices used + * to interface the interrupt handler API + */ + +/* + * Base index for the module specific irq handlers + */ +#define BSP_ASM_IRQ_VECTOR_BASE 0x0 +#define BSP_IPIC_VECTOR_BASE BSP_ASM_IRQ_VECTOR_BASE + +/* + * Peripheral IRQ handlers related definitions + */ +#define BSP_IPIC_PER_IRQ_NUMBER 128 +#define BSP_IPIC_IRQ_LOWEST_OFFSET BSP_IPIC_VECTOR_BASE /* 0 */ +#define BSP_IPIC_IRQ_MAX_OFFSET (BSP_IPIC_IRQ_LOWEST_OFFSET\ + +BSP_IPIC_PER_IRQ_NUMBER-1) + +#define BSP_IS_IPIC_IRQ(irqnum) \ + (((irqnum) >= BSP_IPIC_IRQ_LOWEST_OFFSET) && \ + ((irqnum) <= BSP_IPIC_IRQ_MAX_OFFSET)) +/* + * Processor IRQ handlers related definitions + */ +#define BSP_PROCESSOR_IRQ_NUMBER 1 +#define BSP_PROCESSOR_IRQ_LOWEST_OFFSET (BSP_IPIC_IRQ_MAX_OFFSET+1) +#define BSP_PROCESSOR_IRQ_MAX_OFFSET (BSP_PROCESSOR_IRQ_LOWEST_OFFSET\ + +BSP_PROCESSOR_IRQ_NUMBER-1) + +#define BSP_IS_PROCESSOR_IRQ(irqnum) \ + (((irqnum) >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET) && \ + ((irqnum) <= BSP_PROCESSOR_IRQ_MAX_OFFSET)) +/* + * Summary + */ +#define BSP_IRQ_NUMBER (BSP_PROCESSOR_IRQ_MAX_OFFSET+1) +#define BSP_LOWEST_OFFSET BSP_IPIC_IRQ_LOWEST_OFFSET +#define BSP_MAX_OFFSET BSP_PROCESSOR_IRQ_MAX_OFFSET + +#define BSP_IS_VALID_IRQ(irqnum) \ + (BSP_IS_PROCESSOR_IRQ(irqnum) \ + || BSP_IS_IPIC_IRQ(irqnum)) + +#ifndef ASM +#ifdef __cplusplus +extern "C" { +#endif + +/* + * index table for the module specific handlers, a few entries are only placeholders + */ + typedef enum { + BSP_IPIC_IRQ_FIRST = BSP_IPIC_IRQ_LOWEST_OFFSET, + BSP_IPIC_IRQ_ERROR = BSP_IPIC_IRQ_LOWEST_OFFSET + 0, + /* reserved irqs 1- 8 */ + BSP_IPIC_IRQ_UART1 = BSP_IPIC_IRQ_LOWEST_OFFSET + 9, + BSP_IPIC_IRQ_UART2 = BSP_IPIC_IRQ_LOWEST_OFFSET + 10, + BSP_IPIC_IRQ_SEC = BSP_IPIC_IRQ_LOWEST_OFFSET + 11, + /* reserved irqs 12-13 */ + BSP_IPIC_IRQ_I2C1 = BSP_IPIC_IRQ_LOWEST_OFFSET + 14, + BSP_IPIC_IRQ_I2C2 = BSP_IPIC_IRQ_LOWEST_OFFSET + 15, + BSP_IPIC_IRQ_SPI = BSP_IPIC_IRQ_LOWEST_OFFSET + 16, + BSP_IPIC_IRQ_IRQ1 = BSP_IPIC_IRQ_LOWEST_OFFSET + 17, + BSP_IPIC_IRQ_IRQ2 = BSP_IPIC_IRQ_LOWEST_OFFSET + 18, + BSP_IPIC_IRQ_IRQ3 = BSP_IPIC_IRQ_LOWEST_OFFSET + 19, + BSP_IPIC_IRQ_IRQ4 = BSP_IPIC_IRQ_LOWEST_OFFSET + 20, + BSP_IPIC_IRQ_IRQ5 = BSP_IPIC_IRQ_LOWEST_OFFSET + 21, + BSP_IPIC_IRQ_IRQ6 = BSP_IPIC_IRQ_LOWEST_OFFSET + 22, + BSP_IPIC_IRQ_IRQ7 = BSP_IPIC_IRQ_LOWEST_OFFSET + 23, + /* reserved irqs 24-31 */ + BSP_IPIC_IRQ_TSEC1_TX = BSP_IPIC_IRQ_LOWEST_OFFSET + 32, + BSP_IPIC_IRQ_TSEC1_RX = BSP_IPIC_IRQ_LOWEST_OFFSET + 33, + BSP_IPIC_IRQ_TSEC1_ERR = BSP_IPIC_IRQ_LOWEST_OFFSET + 34, + BSP_IPIC_IRQ_TSEC2_TX = BSP_IPIC_IRQ_LOWEST_OFFSET + 35, + BSP_IPIC_IRQ_TSEC2_RX = BSP_IPIC_IRQ_LOWEST_OFFSET + 36, + BSP_IPIC_IRQ_TSEC2_ERR = BSP_IPIC_IRQ_LOWEST_OFFSET + 37, + BSP_IPIC_IRQ_USB_DR = BSP_IPIC_IRQ_LOWEST_OFFSET + 38, + BSP_IPIC_IRQ_USB_MPH = BSP_IPIC_IRQ_LOWEST_OFFSET + 39, + /* reserved irqs 40-47 */ + BSP_IPIC_IRQ_IRQ0 = BSP_IPIC_IRQ_LOWEST_OFFSET + 48, + /* reserved irqs 49-63 */ + BSP_IPIC_IRQ_RTC_SEC = BSP_IPIC_IRQ_LOWEST_OFFSET + 64, + BSP_IPIC_IRQ_PIT = BSP_IPIC_IRQ_LOWEST_OFFSET + 65, + BSP_IPIC_IRQ_PCI1 = BSP_IPIC_IRQ_LOWEST_OFFSET + 66, + BSP_IPIC_IRQ_PCI2 = BSP_IPIC_IRQ_LOWEST_OFFSET + 67, + BSP_IPIC_IRQ_RTC_ALR = BSP_IPIC_IRQ_LOWEST_OFFSET + 68, + BSP_IPIC_IRQ_MU = BSP_IPIC_IRQ_LOWEST_OFFSET + 69, + BSP_IPIC_IRQ_SBA = BSP_IPIC_IRQ_LOWEST_OFFSET + 70, + BSP_IPIC_IRQ_DMA = BSP_IPIC_IRQ_LOWEST_OFFSET + 71, + BSP_IPIC_IRQ_GTM4 = BSP_IPIC_IRQ_LOWEST_OFFSET + 72, + BSP_IPIC_IRQ_GTM8 = BSP_IPIC_IRQ_LOWEST_OFFSET + 73, + BSP_IPIC_IRQ_GPIO1 = BSP_IPIC_IRQ_LOWEST_OFFSET + 74, + BSP_IPIC_IRQ_GPIO2 = BSP_IPIC_IRQ_LOWEST_OFFSET + 75, + BSP_IPIC_IRQ_DDR = BSP_IPIC_IRQ_LOWEST_OFFSET + 76, + BSP_IPIC_IRQ_LBC = BSP_IPIC_IRQ_LOWEST_OFFSET + 77, + BSP_IPIC_IRQ_GTM2 = BSP_IPIC_IRQ_LOWEST_OFFSET + 78, + BSP_IPIC_IRQ_GTM6 = BSP_IPIC_IRQ_LOWEST_OFFSET + 79, + BSP_IPIC_IRQ_PMC = BSP_IPIC_IRQ_LOWEST_OFFSET + 80, + /* reserved irqs 81-83 */ + BSP_IPIC_IRQ_GTM3 = BSP_IPIC_IRQ_LOWEST_OFFSET + 84, + BSP_IPIC_IRQ_GTM7 = BSP_IPIC_IRQ_LOWEST_OFFSET + 85, + /* reserved irqs 86-89 */ + BSP_IPIC_IRQ_GTM1 = BSP_IPIC_IRQ_LOWEST_OFFSET + 90, + BSP_IPIC_IRQ_GTM5 = BSP_IPIC_IRQ_LOWEST_OFFSET + 91, + /* reserved irqs 92-127 */ + + BSP_IPIC_IRQ_LAST = BSP_IPIC_IRQ_MAX_OFFSET, + BSP_DECREMENTER = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + 0 + } rtems_irq_symbolic_name; + + extern rtems_irq_connect_data *BSP_rtems_irq_tbl; + void BSP_rtems_irq_mng_init(unsigned cpuId); + + /* ipic.c */ + rtems_status_code BSP_irq_handle_at_ipic(uint32_t excNum); + void BSP_irq_enable_at_ipic (rtems_irq_number irqnum); + void BSP_irq_disable_at_ipic (rtems_irq_number irqnum); + +#ifdef __cplusplus +} +#endif +#endif /* ASM */ + +#endif /* GEN83XX_IRQ_IRQ_H */ diff --git a/c/src/lib/libbsp/powerpc/gen83xx/irq/irq_init.c b/c/src/lib/libbsp/powerpc/gen83xx/irq/irq_init.c new file mode 100644 index 0000000000..c930f7bcbf --- /dev/null +++ b/c/src/lib/libbsp/powerpc/gen83xx/irq/irq_init.c @@ -0,0 +1,413 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC83xx BSP | ++-----------------------------------------------------------------+ +| Copyright (c) 2007 | +| 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 init code | ++-----------------------------------------------------------------+ +| derived from the virtex BSP | +\*===============================================================*/ +#include <libcpu/spr.h> +#include <bsp/irq.h> +#include <bsp.h> +#include <libcpu/raw_exception.h> +#include <rtems/bspIo.h> +#include <rtems/powerpc/powerpc.h> +#include <bsp/vectors.h> + +static rtems_irq_connect_data rtemsIrqTbl[BSP_IRQ_NUMBER]; +rtems_irq_connect_data *BSP_rtems_irq_tbl; +rtems_irq_global_settings* BSP_rtems_irq_config; + +/*********************************************************** + * dummy functions for on/off/isOn calls + * these functions just do nothing fulfill the semantic + * requirements to enable/disable a certain interrupt or exception + */ +void BSP_irq_nop_func(const rtems_irq_connect_data *unused) +{ + /* + * nothing to do + */ +} + +void BSP_irq_nop_hdl(void *hdl) +{ + /* + * nothing to do + */ +} + +int BSP_irq_true_func(const rtems_irq_connect_data *unused) +{ + /* + * nothing to do + */ + return TRUE; +} + +/*********************************************************** + * interrupt handler and its enable/disable functions + ***********************************************************/ + +/*********************************************************** + * functions to enable/disable/query external/critical interrupts + */ +void BSP_irqexc_on_fnc(rtems_irq_connect_data *conn_data) +{ + uint32_t msr_value; + /* + * get current MSR value + */ + _CPU_MSR_GET(msr_value); + + + msr_value |= PPC_MSR_EE; + _CPU_MSR_SET(msr_value); +} + +void BSP_irqexc_off_fnc(rtems_irq_connect_data *unused) +{ + /* + * nothing to do + */ +} + +/*********************************************************** + * High level IRQ handler called from shared_raw_irq_code_entry + */ +void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum) +{ + uint32_t msr_value,new_msr; + + /* + * Handle interrupt + */ + switch(excNum) { + case ASM_DEC_VECTOR: + _CPU_MSR_GET(msr_value); + new_msr = msr_value | MSR_EE; + _CPU_MSR_SET(new_msr); + + BSP_rtems_irq_tbl[BSP_DECREMENTER].hdl + (BSP_rtems_irq_tbl[BSP_DECREMENTER].handle); + + _CPU_MSR_SET(msr_value); + + break; +#if 0 /* Critical interrupts not yet supported */ + case ASM_CRIT_VECTOR: +#endif + case ASM_SYSMGMT_VECTOR: + case ASM_EXT_VECTOR: + BSP_irq_handle_at_ipic(excNum); + break; + } +} + +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(); + } +} + +/*********************************************************** + * functions to set/get/remove interrupt handlers + ***********************************************************/ +int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq) +{ + unsigned int level; + /* + * check for valid irq name + * if invalid, print error and return 0 + */ + if (!BSP_IS_VALID_IRQ(irq->name)) { + printk("Invalid interrupt vector %d\n",irq->name); + return 0; + } + + /* + * disable interrupts + */ + _CPU_ISR_Disable(level); + /* + * check, that default handler is installed now + */ + if (rtemsIrqTbl[irq->name].hdl != BSP_rtems_irq_config->defaultEntry.hdl) { + _CPU_ISR_Enable(level); + printk("IRQ vector %d already connected\n",irq->name); + return 0; + } + /* + * store new handler data + */ + rtemsIrqTbl[irq->name] = *irq; + + /* + * enable irq at interrupt controller + */ + if (BSP_IS_IPIC_IRQ(irq->name)) { + BSP_irq_enable_at_ipic(irq->name); + } + /* + * call "on" function to enable interrupt at device + */ + irq->on(irq); + /* + * reenable interrupts + */ + _CPU_ISR_Enable(level); + + return 1; +} + +int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq) +{ + unsigned int level; + + /* + * check for valid IRQ name + */ + if (!BSP_IS_VALID_IRQ(irq->name)) { + return 0; + } + _CPU_ISR_Disable(level); + /* + * return current IRQ entry + */ + *irq = rtemsIrqTbl[irq->name]; + _CPU_ISR_Enable(level); + return 1; +} + +int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) +{ + unsigned int level; + + /* + * check for valid IRQ name + */ + if (!BSP_IS_VALID_IRQ(irq->name)) { + return 0; + } + _CPU_ISR_Disable(level); + /* + * check, that specified handler is really connected now + */ + if (rtemsIrqTbl[irq->name].hdl != irq->hdl) { + _CPU_ISR_Enable(level); + return 0; + } + /* + * disable interrupt at interrupt controller + */ + if (BSP_IS_IPIC_IRQ(irq->name)) { + BSP_irq_disable_at_ipic(irq->name); + } + /* + * disable interrupt at source + */ + irq->off(irq); + /* + * restore default interrupt handler + */ + rtemsIrqTbl[irq->name] = BSP_rtems_irq_config->defaultEntry; + + /* + * reenable interrupts + */ + _CPU_ISR_Enable(level); + + return 1; +} + +/*********************************************************** + * functions to set/get the basic interrupt management setup + ***********************************************************/ +/* + * (Re) get info on current RTEMS interrupt management. + */ +int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** ret_ptr) +{ + *ret_ptr = BSP_rtems_irq_config; + return 0; +} + + +/* + * set management stuff + */ +int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config) +{ + int i; + unsigned int level; + + _CPU_ISR_Disable(level); + /* + * store given configuration + */ + BSP_rtems_irq_config = config; + BSP_rtems_irq_tbl = BSP_rtems_irq_config->irqHdlTbl; + /* + * enable any non-empty IRQ entries at OPBINTC + */ + for (i = BSP_IPIC_IRQ_LOWEST_OFFSET; + i <= BSP_IPIC_IRQ_MAX_OFFSET; + i++) { + if (BSP_rtems_irq_tbl[i].hdl != config->defaultEntry.hdl) { + BSP_irq_enable_at_ipic(i); + BSP_rtems_irq_tbl[i].on((&BSP_rtems_irq_tbl[i])); + } + else { + BSP_rtems_irq_tbl[i].off(&(BSP_rtems_irq_tbl[i])); + BSP_irq_disable_at_ipic(i); + } + } + /* + * store any irq-like processor exceptions + */ + for (i = BSP_PROCESSOR_IRQ_LOWEST_OFFSET; + i < BSP_PROCESSOR_IRQ_MAX_OFFSET; + i++) { + if (BSP_rtems_irq_tbl[i].hdl != config->defaultEntry.hdl) { + if (BSP_rtems_irq_tbl[i].on != NULL) { + BSP_rtems_irq_tbl[i].on + (&(BSP_rtems_irq_tbl[i])); + } + } + else { + if (BSP_rtems_irq_tbl[i].off != NULL) { + BSP_rtems_irq_tbl[i].off + (&(BSP_rtems_irq_tbl[i])); + } + } + } + _CPU_ISR_Enable(level); + return 1; +} +/********************************************** + * list of exception vectors to tap for interrupt handlers + */ +static rtems_raw_except_connect_data BSP_vec_desc[] = { +#if defined(ASM_DEC_VECTOR) + {ASM_DEC_VECTOR, + {ASM_DEC_VECTOR, + decrementer_exception_vector_prolog_code, + (size_t)decrementer_exception_vector_prolog_code_size + }, + exception_nop_enable, + exception_nop_enable, + exception_always_enabled + }, +#endif +#if defined(ASM_SYSMGMT_VECTOR) + {ASM_SYSMGMT_VECTOR, + {ASM_SYSMGMT_VECTOR, + sysmgmt_exception_vector_prolog_code, + (size_t)sysmgmt_exception_vector_prolog_code_size + }, + exception_nop_enable, + exception_nop_enable, + exception_always_enabled + }, +#endif + {ASM_EXT_VECTOR, + {ASM_EXT_VECTOR, + external_exception_vector_prolog_code, + (size_t)&external_exception_vector_prolog_code_size + }, + exception_nop_enable, + exception_nop_enable, + exception_always_enabled + } +#if 0 /* Critical interrupts not yet supported */ + ,{ASM_CRIT_VECTOR, + {ASM_CRIT_VECTOR, + critical_exception_vector_prolog_code, + critical_exception_vector_prolog_code_size + } + BSP_irq_nop_func, + BSP_irq_nop_func, + BSP_irq_true_func + } +#endif +}; + +/* + * dummy for an empty IRQ handler entry + */ +static rtems_irq_connect_data emptyIrq = { + 0, /* Irq Name */ + BSP_irq_nop_hdl, /* handler function */ + NULL, /* handle passed to handler */ + BSP_irq_nop_func, /* on function */ + BSP_irq_nop_func, /* off function */ + BSP_irq_true_func /* isOn function */ +}; + +static rtems_irq_global_settings initialConfig = { + BSP_IRQ_NUMBER, /* irqNb */ + { 0, /* Irq Name */ + BSP_irq_nop_hdl, /* handler function */ + NULL, /* handle passed to handler */ + BSP_irq_nop_func, /* on function */ + BSP_irq_nop_func, /* off function */ + BSP_irq_true_func /* isOn function */ + }, /* emptyIrq */ + rtemsIrqTbl, /* irqHdlTbl */ + 0, /* irqBase */ + NULL /* irqPrioTbl */ +}; + +void BSP_rtems_irq_mng_init(unsigned cpuId) +{ + int i; + /* + * connect all exception vectors needed + */ + for (i = 0; + i < (sizeof(BSP_vec_desc) / + sizeof(BSP_vec_desc[0])); + i++) { + if (!ppc_set_exception (&BSP_vec_desc[i])) { + BSP_panic("Unable to initialize RTEMS raw exception\n"); + } + } + /* + * setup interrupt handlers table + */ + for (i = 0; + i < BSP_IRQ_NUMBER; + i++) { + rtemsIrqTbl[i] = emptyIrq; + rtemsIrqTbl[i].name = i; + } + + /* + * initialize interrupt management + */ + if (!BSP_rtems_irq_mngt_set(&initialConfig)) { + BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); + } +} + |