diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-23 09:50:39 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-23 15:18:44 +0200 |
commit | 8f8ccee0d9e1c3adfb1de484f26f6d9f6ff08708 (patch) | |
tree | 5dc76f7a4527b0a500fbf5ee91486b2780e47a1a /bsps/arm | |
parent | bsps: Move SPI drivers to bsps (diff) | |
download | rtems-8f8ccee0d9e1c3adfb1de484f26f6d9f6ff08708.tar.bz2 |
bsps: Move interrupt controller support to bsps
This patch is a part of the BSP source reorganization.
Update #3285.
Diffstat (limited to 'bsps/arm')
-rw-r--r-- | bsps/arm/beagle/irq/irq.c | 144 | ||||
-rw-r--r-- | bsps/arm/csb336/irq/irq.c | 51 | ||||
-rw-r--r-- | bsps/arm/csb337/irq/irq.c | 56 | ||||
-rw-r--r-- | bsps/arm/edb7312/irq/bsp_irq_asm.S | 323 | ||||
-rw-r--r-- | bsps/arm/edb7312/irq/irq.c | 180 | ||||
-rw-r--r-- | bsps/arm/gdbarmsim/irq/irq-dispatch.c | 50 | ||||
-rw-r--r-- | bsps/arm/gdbarmsim/irq/irq.c | 71 | ||||
-rw-r--r-- | bsps/arm/gumstix/irq/irq.c | 51 | ||||
-rw-r--r-- | bsps/arm/lpc176x/irq/irq.c | 75 | ||||
-rw-r--r-- | bsps/arm/lpc24xx/irq/irq-dispatch.c | 50 | ||||
-rw-r--r-- | bsps/arm/lpc24xx/irq/irq.c | 120 | ||||
-rwxr-xr-x | bsps/arm/lpc32xx/irq/irq.c | 344 | ||||
-rw-r--r-- | bsps/arm/raspberrypi/irq/irq.c | 168 | ||||
-rw-r--r-- | bsps/arm/rtl22xx/irq/irq.c | 70 | ||||
-rw-r--r-- | bsps/arm/shared/irq/irq-armv7m.c | 67 | ||||
-rw-r--r-- | bsps/arm/shared/irq/irq-dispatch-armv7m.c | 32 | ||||
-rw-r--r-- | bsps/arm/shared/irq/irq-gic.c | 180 | ||||
-rw-r--r-- | bsps/arm/smdk2410/irq/irq.c | 45 | ||||
-rw-r--r-- | bsps/arm/tms570/irq/irq.c | 202 |
19 files changed, 2279 insertions, 0 deletions
diff --git a/bsps/arm/beagle/irq/irq.c b/bsps/arm/beagle/irq/irq.c new file mode 100644 index 0000000000..2fa1a5b0f0 --- /dev/null +++ b/bsps/arm/beagle/irq/irq.c @@ -0,0 +1,144 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * @ingroup arm_beagle + * + * @brief Interrupt support. + */ + +/* + * Copyright (c) 2014 Ben Gras <beng@shrike-systems.com>. All rights reserved. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> +#include <bsp/fatal.h> + +#include <rtems/score/armv4.h> + +#include <libcpu/arm-cp15.h> + +struct omap_intr +{ + uint32_t base; + int size; +}; + +#if IS_DM3730 +static struct omap_intr omap_intr = { + .base = OMAP3_DM37XX_INTR_BASE, + .size = 0x1000, +}; +#endif + +#if IS_AM335X +static struct omap_intr omap_intr = { + .base = OMAP3_AM335X_INTR_BASE, + .size = 0x1000, +}; +#endif + +/* Enables interrupts at the Interrupt Controller side. */ +static inline void omap_irq_ack(void) +{ + mmio_write(omap_intr.base + OMAP3_INTCPS_CONTROL, OMAP3_INTR_NEWIRQAGR); + + /* Flush data cache to make sure all the previous writes are done + before re-enabling interrupts. */ + flush_data_cache(); +} + +void bsp_interrupt_dispatch(void) +{ + const uint32_t reg = mmio_read(omap_intr.base + OMAP3_INTCPS_SIR_IRQ); + + if ((reg & OMAP3_INTR_SPURIOUSIRQ_MASK) != OMAP3_INTR_SPURIOUSIRQ_MASK) { + const rtems_vector_number irq = reg & OMAP3_INTR_ACTIVEIRQ_MASK; + + bsp_interrupt_handler_dispatch(irq); + } else { + /* Ignore spurious interrupts. We'll still ACK it so new interrupts + can be generated. */ + } + + omap_irq_ack(); +} + +/* There are 4 32-bit interrupt mask registers for a total of 128 interrupts. + The IRQ number tells us which register to use. */ +static uint32_t omap_get_mir_reg(rtems_vector_number vector, uint32_t *const mask) +{ + uint32_t mir_reg; + + /* Select which bit to set/clear in the MIR register. */ + *mask = 1ul << (vector % 32u); + + if (vector < 32u) { + mir_reg = OMAP3_INTCPS_MIR0; + } else if (vector < 64u) { + mir_reg = OMAP3_INTCPS_MIR1; + } else if (vector < 96u) { + mir_reg = OMAP3_INTCPS_MIR2; + } else if (vector < 128u) { + mir_reg = OMAP3_INTCPS_MIR3; + } else { + /* Invalid IRQ number. This should never happen. */ + bsp_fatal(0); + } + + return mir_reg; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + uint32_t mask, cur; + uint32_t mir_reg = omap_get_mir_reg(vector, &mask); + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + cur = mmio_read(omap_intr.base + mir_reg); + mmio_write(omap_intr.base + mir_reg, cur & ~mask); + flush_data_cache(); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + uint32_t mask, cur; + uint32_t mir_reg = omap_get_mir_reg(vector, &mask); + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + cur = mmio_read(omap_intr.base + mir_reg); + mmio_write(omap_intr.base + mir_reg, cur | mask); + flush_data_cache(); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + int i; + uint32_t intc_ilrx; + + /* AM335X TRM 6.2.1 Initialization Sequence */ + mmio_write(omap_intr.base + OMAP3_INTCPS_SYSCONFIG, OMAP3_SYSCONFIG_AUTOIDLE); + mmio_write(omap_intr.base + OMAP3_INTCPS_IDLE, 0); + /* priority 0 to all IRQs */ + for(intc_ilrx = 0x100; intc_ilrx <= 0x2fc; intc_ilrx += 4) { + mmio_write(omap_intr.base + intc_ilrx, 0); + } + + /* Mask all interrupts */ + for(i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; i++) + bsp_interrupt_vector_disable(i); + + /* Install generic interrupt handler */ + arm_cp15_set_exception_handler(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt); + arm_cp15_set_vector_base_address(bsp_vector_table_begin); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/csb336/irq/irq.c b/bsps/arm/csb336/irq/irq.c new file mode 100644 index 0000000000..e5887b9717 --- /dev/null +++ b/bsps/arm/csb336/irq/irq.c @@ -0,0 +1,51 @@ +/* + * Motorola MC9328MXL Interrupt handler + * + * Copyright (c) 2010 embedded brains GmbH. + * + * Copyright (c) 2004 by Jay Monkman <jtm@lopingdog.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/armv4.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> + +#include <mc9328mxl.h> + +void bsp_interrupt_dispatch(void) +{ + + rtems_vector_number vector = MC9328MXL_AITC_NIVECSR >> 16; + + bsp_interrupt_handler_dispatch(vector); +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if (vector < MC9328MXL_NUM_INTS) + MC9328MXL_AITC_INTENNUM = vector; +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if (vector < MC9328MXL_NUM_INTS) + MC9328MXL_AITC_INTDISNUM = vector; +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/csb337/irq/irq.c b/bsps/arm/csb337/irq/irq.c new file mode 100644 index 0000000000..95e93845b9 --- /dev/null +++ b/bsps/arm/csb337/irq/irq.c @@ -0,0 +1,56 @@ +/* + * Atmel AT91RM9200 Interrupt handler + * + * Copyright (c) 2010 embedded brains GmbH. + * + * Copyright (c) 2004 by Jay Monkman <jtm@lopingdog.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/armv4.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> + +#include <at91rm9200.h> + +void bsp_interrupt_dispatch(void) +{ + rtems_vector_number vector = AIC_CTL_REG(AIC_IVR); + + bsp_interrupt_handler_dispatch(vector); + + AIC_CTL_REG(AIC_EOICR) = 0; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + AIC_CTL_REG(AIC_IECR) = 1 << vector; +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + AIC_CTL_REG(AIC_IDCR) = 1 << vector; +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + unsigned long i = 0; + + for (i = 0; i < 32; ++i) { + AIC_SVR_REG(i<<2) = i; + } + + /* disable all interrupts */ + AIC_CTL_REG(AIC_IDCR) = 0xffffffff; + + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/edb7312/irq/bsp_irq_asm.S b/bsps/arm/edb7312/irq/bsp_irq_asm.S new file mode 100644 index 0000000000..c48466967b --- /dev/null +++ b/bsps/arm/edb7312/irq/bsp_irq_asm.S @@ -0,0 +1,323 @@ +/* + * Cirrus EP7312 Intererrupt handler + */ + +/* + * Copyright (c) 2002 by Jay Monkman <jtm@smoothsmoothie.com> + * + * Copyright (c) 2002 by Charlie Steader <charlies@poliac.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. +*/ + +#define __asm__ +#include <bsp.h> +#include <bsp/irq.h> + + .extern edb7312_interrupt_dispatch + +/* + * Function to obtain, execute an IT handler and acknowledge the IT + */ + + .globl bsp_interrupt_dispatch +bsp_interrupt_dispatch : +/* + * Look at interrupt status register to determine source. + * From source, determine offset into expanded vector table + * and load handler address into r0. + */ + + ldr r1, =0x80000000 /* close to interrupt status/mask registers 1 */ + ldr r2, =0x80001000 /* close to interrupt status/mask registers 2 */ + ldr r3, =0x80002000 /* close to interrupt status/mask registers 3 */ + + stmdb sp!,{r4, r5, r6} + +/* + * INTSR3 + */ +check_dai: + ldr r4, [r3, #0x240] + ldr r5, [r3, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ + tst r6, #0x0001 + beq check_extfiq + mov r0, #BSP_DAIINT + b get_handler + +/* + * INTSR1 + */ +check_extfiq: + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ + tst r6, #0x0001 + beq check_bl + mov r0, #BSP_EXTFIQ + b get_handler + +check_bl: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0002 + beq check_we + mov r0, #BSP_BLINT + b get_handler + +check_we: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0004 + beq check_mc + mov r0, #BSP_WEINT + b get_handler + +check_mc: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0008 + beq check_cs + mov r0, #BSP_MCINT + b get_handler + +check_cs: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0010 + beq check_e1 + mov r0, #BSP_CSINT + b get_handler + +check_e1: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0020 + beq check_e2 + mov r0, #BSP_EINT1 + b get_handler + +check_e2: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0040 + beq check_e3 + mov r0, #BSP_EINT2 + b get_handler + +check_e3: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0080 + beq check_tc1 + mov r0, #BSP_EINT3 + b get_handler + +check_tc1: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0100 + beq check_tc2 + mov r0, #BSP_TC1OI + b get_handler + +check_tc2: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0200 + beq check_rtc + mov r0, #BSP_TC2OI + b get_handler + +check_rtc: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0400 + beq check_tick + mov r0, #BSP_RTCMI + b get_handler + +check_tick: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0800 + beq check_utx1 + mov r0, #BSP_TINT + b get_handler + +check_utx1: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x1000 + beq check_urx1 + mov r0, #BSP_UTXINT1 + b get_handler + +check_urx1: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x2000 + beq check_ums + mov r0, #BSP_URXINT1 + b get_handler + +check_ums: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x4000 + beq check_sse + mov r0, #BSP_UMSINT + b get_handler + +check_sse: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x8000 + beq check_kbd + mov r0, #BSP_SSEOTI + b get_handler + +/* + * INTSR2 + */ +check_kbd: + ldr r4, [r2, #0x240] + ldr r5, [r2, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ + tst r6, #0x0001 + beq check_ss2rx + mov r0, #BSP_KBDINT + b get_handler + +check_ss2rx: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r2, #0x240] + ldr r5, [r2, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0002 + beq check_ss2tx + mov r0, #BSP_SS2RX + b get_handler + +check_ss2tx: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r2, #0x240] + ldr r5, [r2, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0004 + beq check_utx2 + mov r0, #BSP_SS2TX + b get_handler + +check_utx2: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r2, #0x240] + ldr r5, [r2, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x1000 + beq check_urx2 + mov r0, #BSP_UTXINT2 + b get_handler + +check_urx2: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r2, #0x240] + ldr r5, [r2, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x2000 + beq IRQ_NoInterrupt + mov r0, #BSP_URXINT2 + b get_handler + +get_handler: + + ldmia sp!,{r4, r5, r6} + + /* + * re-enable interrupts at processor level as the current + * interrupt source is now masked via VEGA logic + */ +/* + mrs r1, cpsr + and r1, r1, #0xFFFFFF3F + msr cpsr, r1 +*/ + + stmdb sp!,{lr} + bl edb7312_interrupt_dispatch + ldmia sp!,{lr} + +IRQ_NoInterrupt: + /* return to the "main" interrupt handler */ + mov pc, lr diff --git a/bsps/arm/edb7312/irq/irq.c b/bsps/arm/edb7312/irq/irq.c new file mode 100644 index 0000000000..1d9151a1bd --- /dev/null +++ b/bsps/arm/edb7312/irq/irq.c @@ -0,0 +1,180 @@ +/* + * Cirrus EP7312 Intererrupt handler + */ + +/* + * Copyright (c) 2010 embedded brains GmbH. + * + * Copyright (c) 2002 by Jay Monkman <jtm@smoothsmoothie.com> + * + * Copyright (c) 2002 by Charlie Steader <charlies@poliac.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. +*/ + +#include <rtems/score/armv4.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> + +#include <ep7312.h> + +void edb7312_interrupt_dispatch(rtems_vector_number vector) +{ + bsp_interrupt_handler_dispatch(vector); +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if(vector >= BSP_EXTFIQ && vector <= BSP_SSEOTI) + { + /* interrupt managed by INTMR1 and INTSR1 */ + *EP7312_INTMR1 |= (1 << vector); + } + else if(vector >= BSP_KBDINT && vector <= BSP_SS2TX) + { + /* interrupt managed by INTMR2 and INTSR2 */ + *EP7312_INTMR2 |= (1 << (vector - 16)); + } + else if(vector >= BSP_UTXINT2 && vector <= BSP_URXINT2) + { + /* interrupt managed by INTMR2 and INTSR2 */ + *EP7312_INTMR2 |= (1 << (vector - 7)); + } + else if(vector == BSP_DAIINT) + { + /* interrupt managed by INTMR3 and INTSR3 */ + *EP7312_INTMR3 |= (1 << (vector - 21)); + } +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if(vector >= BSP_EXTFIQ && vector <= BSP_SSEOTI) + { + /* interrupt managed by INTMR1 and INTSR1 */ + *EP7312_INTMR1 &= ~(1 << vector); + } + else if(vector >= BSP_KBDINT && vector <= BSP_SS2TX) + { + /* interrupt managed by INTMR2 and INTSR2 */ + *EP7312_INTMR2 &= ~(1 << (vector - 16)); + } + else if(vector >= BSP_UTXINT2 && vector <= BSP_URXINT2) + { + /* interrupt managed by INTMR2 and INTSR2 */ + *EP7312_INTMR2 &= ~(1 << (vector - 7)); + } + else if(vector == BSP_DAIINT) + { + /* interrupt managed by INTMR3 and INTSR3 */ + *EP7312_INTMR3 &= ~(1 << (vector - 21)); + } +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + uint32_t int_stat = 0; + + /* mask all interrupts */ + *EP7312_INTMR1 = 0x0; + *EP7312_INTMR2 = 0x0; + *EP7312_INTMR3 = 0x0; + + /* clear all pending interrupt status' */ + int_stat = *EP7312_INTSR1; + if(int_stat & EP7312_INTR1_EXTFIQ) + { + } + if(int_stat & EP7312_INTR1_BLINT) + { + *EP7312_BLEOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_WEINT) + { + *EP7312_TEOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_MCINT) + { + } + if(int_stat & EP7312_INTR1_CSINT) + { + *EP7312_COEOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_EINT1) + { + } + if(int_stat & EP7312_INTR1_EINT2) + { + } + if(int_stat & EP7312_INTR1_EINT3) + { + } + if(int_stat & EP7312_INTR1_TC1OI) + { + *EP7312_TC1EOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_TC2OI) + { + *EP7312_TC2EOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_RTCMI) + { + *EP7312_RTCEOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_TINT) + { + *EP7312_TEOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_URXINT1) + { + } + if(int_stat & EP7312_INTR1_UTXINT1) + { + } + if(int_stat & EP7312_INTR1_UMSINT) + { + *EP7312_UMSEOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_SSEOTI) + { + *EP7312_SYNCIO; + } + int_stat = *EP7312_INTSR1; + + int_stat = *EP7312_INTSR2; + if(int_stat & EP7312_INTR2_KBDINT) + { + *EP7312_KBDEOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR2_SS2RX) + { + } + if(int_stat & EP7312_INTR2_SS2TX) + { + } + if(int_stat & EP7312_INTR2_URXINT2) + { + } + if(int_stat & EP7312_INTR2_UTXINT2) + { + } + int_stat = *EP7312_INTSR2; + + int_stat = *EP7312_INTSR3; + if(int_stat & EP7312_INTR2_DAIINT) + { + } + int_stat = *EP7312_INTSR3; + + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/gdbarmsim/irq/irq-dispatch.c b/bsps/arm/gdbarmsim/irq/irq-dispatch.c new file mode 100644 index 0000000000..f045fb8149 --- /dev/null +++ b/bsps/arm/gdbarmsim/irq/irq-dispatch.c @@ -0,0 +1,50 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * + * @brief GDB ARM Simulator interrupt support. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/armv4.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> + +#ifdef ARM_MULTILIB_ARCH_V4 + +void bsp_interrupt_dispatch(void) +{ + /* Read current vector number */ + /* rtems_vector_number vector = VICVectAddr; */ + rtems_vector_number vector = 0; + + /* Enable interrupts in program status register */ + uint32_t psr = _ARMV4_Status_irq_enable(); + + /* Dispatch interrupt handlers */ + bsp_interrupt_handler_dispatch(vector); + + /* Restore program status register */ + _ARMV4_Status_restore(psr); + + /* Acknowledge interrupt */ + //VICVectAddr = 0; +} + +#endif /* ARM_MULTILIB_ARCH_V4 */ diff --git a/bsps/arm/gdbarmsim/irq/irq.c b/bsps/arm/gdbarmsim/irq/irq.c new file mode 100644 index 0000000000..886f928d2d --- /dev/null +++ b/bsps/arm/gdbarmsim/irq/irq.c @@ -0,0 +1,71 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * + * @brief GDB ARM Simulator interrupt support. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/armv4.h> +#include <rtems/score/armv7m.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> + +/* + * Prototypes + */ +void lpc24xx_irq_set_priority(rtems_vector_number, unsigned); +unsigned lpc24xx_irq_get_priority(rtems_vector_number); + +static inline bool lpc24xx_irq_is_valid(rtems_vector_number vector) +{ + return vector <= BSP_INTERRUPT_VECTOR_MAX; +} + +void lpc24xx_irq_set_priority(rtems_vector_number vector, unsigned priority) +{ +} + +unsigned lpc24xx_irq_get_priority(rtems_vector_number vector) +{ + return 0; /* bogus value to avoid warning */ +} + +#ifdef ARM_MULTILIB_ARCH_V4 + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + /* Install the IRQ exception handler */ + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} + +#endif /* ARM_MULTILIB_ARCH_V4 */ diff --git a/bsps/arm/gumstix/irq/irq.c b/bsps/arm/gumstix/irq/irq.c new file mode 100644 index 0000000000..425795b165 --- /dev/null +++ b/bsps/arm/gumstix/irq/irq.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010 embedded brains GmbH. + * + * PXA255 Interrupt handler by Yang Xi <hiyangxi@gmail.com> + * Copyright (c) 2004 by Jay Monkman <jtm@lopingdog.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/armv4.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> + +#include <pxa255.h> + +void bsp_interrupt_dispatch(void) +{ + rtems_vector_number vector = 31 - __builtin_clz(XSCALE_INT_ICIP); + + bsp_interrupt_handler_dispatch(vector); +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + XSCALE_INT_ICMR |= 1 << vector; +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + XSCALE_INT_ICMR &= ~(1 << vector); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + /* disable all interrupts */ + XSCALE_INT_ICMR = 0x0; + + /* Direct the interrupt to IRQ*/ + XSCALE_INT_ICLR = 0x0; + + /* Install the IRQ exception handler */ + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/lpc176x/irq/irq.c b/bsps/arm/lpc176x/irq/irq.c new file mode 100644 index 0000000000..e05fd59e6c --- /dev/null +++ b/bsps/arm/lpc176x/irq/irq.c @@ -0,0 +1,75 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * + * @brief LPC176X interrupt support. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/armv4.h> +#include <rtems/score/armv7m.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/lpc176x.h> +#include <bsp/linker-symbols.h> + +/** + * @brief Checks if the current interrupt vector length is valid or not. + * + * @param vector The current interrupt vector length. + * @return TRUE if valid. + * FALSE otherwise. + */ +static inline bool lpc176x_irq_is_valid( const rtems_vector_number vector ) +{ + return vector <= BSP_INTERRUPT_VECTOR_MAX; +} + +void lpc176x_irq_set_priority( + const rtems_vector_number vector, + unsigned priority +) +{ + if ( lpc176x_irq_is_valid( vector ) ) { + if ( priority > LPC176X_IRQ_PRIORITY_VALUE_MAX ) { + priority = LPC176X_IRQ_PRIORITY_VALUE_MAX; + } + + /* else implies that the priority is unlocked. Also, + there is nothing to do. */ + + _ARMV7M_NVIC_Set_priority( (int) vector, (int) ( priority << 3u ) ); + } + + /* else implies that the rtems vector number is invalid. Also, + there is nothing to do. */ +} + +unsigned lpc176x_irq_get_priority( const rtems_vector_number vector ) +{ + unsigned priority; + + if ( lpc176x_irq_is_valid( vector ) ) { + priority = (unsigned) ( _ARMV7M_NVIC_Get_priority( (int) vector ) >> 3u ); + } else { + priority = LPC176X_IRQ_PRIORITY_VALUE_MIN - 1u; + } + + return priority; +} diff --git a/bsps/arm/lpc24xx/irq/irq-dispatch.c b/bsps/arm/lpc24xx/irq/irq-dispatch.c new file mode 100644 index 0000000000..66d05fdf9d --- /dev/null +++ b/bsps/arm/lpc24xx/irq/irq-dispatch.c @@ -0,0 +1,50 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * + * @brief LPC24XX interrupt support. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/armv4.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/lpc24xx.h> + +#ifdef ARM_MULTILIB_ARCH_V4 + +void bsp_interrupt_dispatch(void) +{ + /* Read current vector number */ + rtems_vector_number vector = VICVectAddr; + + /* Enable interrupts in program status register */ + uint32_t psr = _ARMV4_Status_irq_enable(); + + /* Dispatch interrupt handlers */ + bsp_interrupt_handler_dispatch(vector); + + /* Restore program status register */ + _ARMV4_Status_restore(psr); + + /* Acknowledge interrupt */ + VICVectAddr = 0; +} + +#endif /* ARM_MULTILIB_ARCH_V4 */ diff --git a/bsps/arm/lpc24xx/irq/irq.c b/bsps/arm/lpc24xx/irq/irq.c new file mode 100644 index 0000000000..7801c37843 --- /dev/null +++ b/bsps/arm/lpc24xx/irq/irq.c @@ -0,0 +1,120 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * + * @brief LPC24XX interrupt support. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/armv4.h> +#include <rtems/score/armv7m.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/lpc24xx.h> +#include <bsp/linker-symbols.h> + +static inline bool lpc24xx_irq_is_valid(rtems_vector_number vector) +{ + return vector <= BSP_INTERRUPT_VECTOR_MAX; +} + +void lpc24xx_irq_set_priority(rtems_vector_number vector, unsigned priority) +{ + if (lpc24xx_irq_is_valid(vector)) { + if (priority > LPC24XX_IRQ_PRIORITY_VALUE_MAX) { + priority = LPC24XX_IRQ_PRIORITY_VALUE_MAX; + } + + #ifdef ARM_MULTILIB_ARCH_V4 + VICVectPriorityBase [vector] = priority; + #else + _ARMV7M_NVIC_Set_priority((int) vector, (int) (priority << 3)); + #endif + } +} + +unsigned lpc24xx_irq_get_priority(rtems_vector_number vector) +{ + if (lpc24xx_irq_is_valid(vector)) { + #ifdef ARM_MULTILIB_ARCH_V4 + return VICVectPriorityBase [vector]; + #else + return (unsigned) (_ARMV7M_NVIC_Get_priority((int) vector) >> 3); + #endif + } else { + return LPC24XX_IRQ_PRIORITY_VALUE_MIN - 1U; + } +} + +#ifdef ARM_MULTILIB_ARCH_V4 + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + VICIntEnable = 1U << vector; +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + VICIntEnClear = 1U << vector; +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + volatile uint32_t *addr = VICVectAddrBase; + volatile uint32_t *prio = VICVectPriorityBase; + rtems_vector_number i = 0; + + /* Disable all interrupts */ + VICIntEnClear = 0xffffffff; + + /* Clear all software interrupts */ + VICSoftIntClear = 0xffffffff; + + /* Use IRQ category */ + VICIntSelect = 0; + + for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) { + /* Use the vector address register to store the vector number */ + addr [i] = i; + + /* Give vector lowest priority */ + prio [i] = 15; + } + + /* Reset priority mask register */ + VICSWPrioMask = 0xffff; + + /* Acknowledge interrupts for all priorities */ + for ( + i = LPC24XX_IRQ_PRIORITY_VALUE_MIN; + i <= LPC24XX_IRQ_PRIORITY_VALUE_MAX; + ++i + ) { + VICVectAddr = 0; + } + + /* Install the IRQ exception handler */ + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} + +#endif /* ARM_MULTILIB_ARCH_V4 */ diff --git a/bsps/arm/lpc32xx/irq/irq.c b/bsps/arm/lpc32xx/irq/irq.c new file mode 100755 index 0000000000..eac320000b --- /dev/null +++ b/bsps/arm/lpc32xx/irq/irq.c @@ -0,0 +1,344 @@ +/** + * @file + * + * @ingroup lpc32xx_interrupt + * + * @brief Interrupt support. + */ + +/* + * Copyright (c) 2009 + * embedded brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/armv4.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/lpc32xx.h> +#include <bsp/linker-symbols.h> +#include <bsp/mmu.h> + +/* + * Mask out SIC 1 and 2 IRQ request. There is no need to mask out the FIQ, + * since a pending FIQ would be a fatal error. The default handler will be + * invoked in this case. + */ +#define LPC32XX_MIC_STATUS_MASK (~0x3U) + +typedef union { + struct { + uint32_t mic; + uint32_t sic_1; + uint32_t sic_2; + } field; + uint32_t fields_table [LPC32XX_IRQ_MODULE_COUNT]; +} lpc32xx_irq_fields; + +static uint8_t lpc32xx_irq_priority_table [LPC32XX_IRQ_COUNT]; + +static lpc32xx_irq_fields lpc32xx_irq_priority_masks [LPC32XX_IRQ_PRIORITY_COUNT]; + +static lpc32xx_irq_fields lpc32xx_irq_enable; + +static inline bool lpc32xx_irq_priority_is_valid(unsigned priority) +{ + return priority <= LPC32XX_IRQ_PRIORITY_LOWEST; +} + +#define LPC32XX_IRQ_BIT_OPS_DEFINE \ + unsigned bit = index & 0x1fU; \ + unsigned module = index >> 5 + +#define LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE \ + LPC32XX_IRQ_BIT_OPS_DEFINE; \ + unsigned module_offset = module << 14; \ + volatile uint32_t *reg = (volatile uint32_t *) \ + ((volatile char *) &lpc32xx.mic + module_offset + register_offset) + +#define LPC32XX_IRQ_OFFSET_ER 0U +#define LPC32XX_IRQ_OFFSET_RSR 4U +#define LPC32XX_IRQ_OFFSET_SR 8U +#define LPC32XX_IRQ_OFFSET_APR 12U +#define LPC32XX_IRQ_OFFSET_ATR 16U +#define LPC32XX_IRQ_OFFSET_ITR 20U + +static inline bool lpc32xx_irq_is_bit_set_in_register(unsigned index, unsigned register_offset) +{ + LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE; + + return *reg & (1U << bit); +} + +static inline void lpc32xx_irq_set_bit_in_register(unsigned index, unsigned register_offset) +{ + LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE; + + *reg |= 1U << bit; +} + +static inline void lpc32xx_irq_clear_bit_in_register(unsigned index, unsigned register_offset) +{ + LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE; + + *reg &= ~(1U << bit); +} + +static inline void lpc32xx_irq_set_bit_in_field(unsigned index, lpc32xx_irq_fields *fields) +{ + LPC32XX_IRQ_BIT_OPS_DEFINE; + + fields->fields_table [module] |= 1U << bit; +} + +static inline void lpc32xx_irq_clear_bit_in_field(unsigned index, lpc32xx_irq_fields *fields) +{ + LPC32XX_IRQ_BIT_OPS_DEFINE; + + fields->fields_table [module] &= ~(1U << bit); +} + +static inline unsigned lpc32xx_irq_get_index(uint32_t val) +{ + ARM_SWITCH_REGISTERS; + + __asm__ volatile ( + ARM_SWITCH_TO_ARM + "clz %[val], %[val]\n" + "rsb %[val], %[val], #31\n" + ARM_SWITCH_BACK + : [val] "=r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT + : "[val]" (val) + ); + + return val; +} + +void lpc32xx_irq_set_priority(rtems_vector_number vector, unsigned priority) +{ + if (bsp_interrupt_is_valid_vector(vector)) { + rtems_interrupt_level level; + unsigned i = 0; + + if (priority > LPC32XX_IRQ_PRIORITY_LOWEST) { + priority = LPC32XX_IRQ_PRIORITY_LOWEST; + } + + lpc32xx_irq_priority_table [vector] = (uint8_t) priority; + + for (i = LPC32XX_IRQ_PRIORITY_HIGHEST; i <= priority; ++i) { + rtems_interrupt_disable(level); + lpc32xx_irq_clear_bit_in_field(vector, &lpc32xx_irq_priority_masks [i]); + rtems_interrupt_enable(level); + } + + for (i = priority + 1; i <= LPC32XX_IRQ_PRIORITY_LOWEST; ++i) { + rtems_interrupt_disable(level); + lpc32xx_irq_set_bit_in_field(vector, &lpc32xx_irq_priority_masks [i]); + rtems_interrupt_enable(level); + } + } +} + +unsigned lpc32xx_irq_get_priority(rtems_vector_number vector) +{ + if (bsp_interrupt_is_valid_vector(vector)) { + return lpc32xx_irq_priority_table [vector]; + } else { + return LPC32XX_IRQ_PRIORITY_LOWEST; + } +} + +void lpc32xx_irq_set_activation_polarity(rtems_vector_number vector, lpc32xx_irq_activation_polarity activation_polarity) +{ + if (bsp_interrupt_is_valid_vector(vector)) { + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + if (activation_polarity == LPC32XX_IRQ_ACTIVE_HIGH_OR_RISING_EDGE) { + lpc32xx_irq_set_bit_in_register(vector, LPC32XX_IRQ_OFFSET_APR); + } else { + lpc32xx_irq_clear_bit_in_register(vector, LPC32XX_IRQ_OFFSET_APR); + } + rtems_interrupt_enable(level); + } +} + +lpc32xx_irq_activation_polarity lpc32xx_irq_get_activation_polarity(rtems_vector_number vector) +{ + if (bsp_interrupt_is_valid_vector(vector)) { + if (lpc32xx_irq_is_bit_set_in_register(vector, LPC32XX_IRQ_OFFSET_APR)) { + return LPC32XX_IRQ_ACTIVE_HIGH_OR_RISING_EDGE; + } else { + return LPC32XX_IRQ_ACTIVE_LOW_OR_FALLING_EDGE; + } + } else { + return LPC32XX_IRQ_ACTIVE_LOW_OR_FALLING_EDGE; + } +} + +void lpc32xx_irq_set_activation_type(rtems_vector_number vector, lpc32xx_irq_activation_type activation_type) +{ + if (bsp_interrupt_is_valid_vector(vector)) { + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + if (activation_type == LPC32XX_IRQ_EDGE_SENSITIVE) { + lpc32xx_irq_set_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ATR); + } else { + lpc32xx_irq_clear_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ATR); + } + rtems_interrupt_enable(level); + } +} + +lpc32xx_irq_activation_type lpc32xx_irq_get_activation_type(rtems_vector_number vector) +{ + if (bsp_interrupt_is_valid_vector(vector)) { + if (lpc32xx_irq_is_bit_set_in_register(vector, LPC32XX_IRQ_OFFSET_ATR)) { + return LPC32XX_IRQ_EDGE_SENSITIVE; + } else { + return LPC32XX_IRQ_LEVEL_SENSITIVE; + } + } else { + return LPC32XX_IRQ_LEVEL_SENSITIVE; + } +} + +void bsp_interrupt_dispatch(void) +{ + uint32_t status = lpc32xx.mic.sr & LPC32XX_MIC_STATUS_MASK; + uint32_t er_mic = lpc32xx.mic.er; + uint32_t er_sic_1 = lpc32xx.sic_1.er; + uint32_t er_sic_2 = lpc32xx.sic_2.er; + uint32_t psr = 0; + lpc32xx_irq_fields *masks = NULL; + rtems_vector_number vector = 0; + unsigned priority = 0; + + if (status != 0) { + vector = lpc32xx_irq_get_index(status); + } else { + status = lpc32xx.sic_1.sr; + if (status != 0) { + vector = lpc32xx_irq_get_index(status) + LPC32XX_IRQ_MODULE_SIC_1; + } else { + status = lpc32xx.sic_2.sr; + if (status != 0) { + vector = lpc32xx_irq_get_index(status) + LPC32XX_IRQ_MODULE_SIC_2; + } else { + return; + } + } + } + + priority = lpc32xx_irq_priority_table [vector]; + + masks = &lpc32xx_irq_priority_masks [priority]; + + lpc32xx.mic.er = er_mic & masks->field.mic; + lpc32xx.sic_1.er = er_sic_1 & masks->field.sic_1; + lpc32xx.sic_2.er = er_sic_2 & masks->field.sic_2; + + psr = _ARMV4_Status_irq_enable(); + + bsp_interrupt_handler_dispatch(vector); + + _ARMV4_Status_restore(psr); + + lpc32xx.mic.er = er_mic & lpc32xx_irq_enable.field.mic; + lpc32xx.sic_1.er = er_sic_1 & lpc32xx_irq_enable.field.sic_1; + lpc32xx.sic_2.er = er_sic_2 & lpc32xx_irq_enable.field.sic_2; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + rtems_interrupt_level level; + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + rtems_interrupt_disable(level); + lpc32xx_irq_set_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ER); + lpc32xx_irq_set_bit_in_field(vector, &lpc32xx_irq_enable); + rtems_interrupt_enable(level); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + rtems_interrupt_level level; + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + rtems_interrupt_disable(level); + lpc32xx_irq_clear_bit_in_field(vector, &lpc32xx_irq_enable); + lpc32xx_irq_clear_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ER); + rtems_interrupt_enable(level); +} + +void lpc32xx_set_exception_handler( + Arm_symbolic_exception_name exception, + void (*handler)(void) +) +{ + if ((unsigned) exception < MAX_EXCEPTIONS) { + uint32_t *table = (uint32_t *) bsp_vector_table_begin + MAX_EXCEPTIONS; + + table [exception] = (uint32_t) handler; + + #ifndef LPC32XX_DISABLE_MMU + rtems_cache_flush_multiple_data_lines(table, 64); + rtems_cache_invalidate_multiple_instruction_lines(NULL, 64); + #endif + } +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + size_t i = 0; + + /* Set default priority */ + for (i = 0; i < LPC32XX_IRQ_COUNT; ++i) { + lpc32xx_irq_priority_table [i] = LPC32XX_IRQ_PRIORITY_LOWEST; + } + + /* Enable SIC 1 and 2 at all priorities */ + for (i = 0; i < LPC32XX_IRQ_PRIORITY_COUNT; ++i) { + lpc32xx_irq_priority_masks [i].field.mic = 0xc0000003; + } + + /* Disable all interrupts except SIC 1 and 2 */ + lpc32xx_irq_enable.field.sic_2 = 0x0; + lpc32xx_irq_enable.field.sic_1 = 0x0; + lpc32xx_irq_enable.field.mic = 0xc0000003; + lpc32xx.sic_1.er = 0x0; + lpc32xx.sic_2.er = 0x0; + lpc32xx.mic.er = 0xc0000003; + + /* Set interrupt types to IRQ */ + lpc32xx.mic.itr = 0x0; + lpc32xx.sic_1.itr = 0x0; + lpc32xx.sic_2.itr = 0x0; + + /* Set interrupt activation polarities */ + lpc32xx.mic.apr = 0x3ff0efe0; + lpc32xx.sic_1.apr = 0xfbd27184; + lpc32xx.sic_2.apr = 0x801810c0; + + /* Set interrupt activation types */ + lpc32xx.mic.atr = 0x0; + lpc32xx.sic_1.atr = 0x26000; + lpc32xx.sic_2.atr = 0x0; + + lpc32xx_set_exception_handler(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/raspberrypi/irq/irq.c b/bsps/arm/raspberrypi/irq/irq.c new file mode 100644 index 0000000000..5b10385bfe --- /dev/null +++ b/bsps/arm/raspberrypi/irq/irq.c @@ -0,0 +1,168 @@ +/** + * @file irq.c + * + * @ingroup raspberrypi_interrupt + * + * @brief Interrupt support. + */ + +/* + * Copyright (c) 2014 Andre Marques <andre.lousa.marques at gmail.com> + * + * Copyright (c) 2009 + * embedded brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/armv4.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/raspberrypi.h> +#include <bsp/linker-symbols.h> +#include <bsp/mmu.h> +#include <rtems/bspIo.h> +#include <strings.h> + +#ifdef RTEMS_SMP +#include <rtems/score/smp.h> +#include <rtems/score/smpimpl.h> +#endif + +typedef struct { + unsigned long enable_reg_addr; + unsigned long disable_reg_addr; +} bcm2835_irq_ctrl_reg_t; + +static const bcm2835_irq_ctrl_reg_t bcm2835_irq_ctrl_reg_table[] = { + { BCM2835_IRQ_ENABLE1, BCM2835_IRQ_DISABLE1 }, + { BCM2835_IRQ_ENABLE2, BCM2835_IRQ_DISABLE2 }, + { BCM2835_IRQ_ENABLE_BASIC, BCM2835_IRQ_DISABLE_BASIC } +}; + +static inline const bcm2835_irq_ctrl_reg_t * +bsp_vector_to_reg(rtems_vector_number vector) +{ + return bcm2835_irq_ctrl_reg_table + (vector >> 5); +} + +static inline uint32_t +bsp_vector_to_mask(rtems_vector_number vector) +{ + return 1 << (vector & 0x1f); +} + +static const int bcm2835_irq_speedup_table[] = +{ + /* 0 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 0, + /* 1 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 1, + /* 2 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 2, + /* 3 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 3, + /* 4 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 4, + /* 5 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 5, + /* 6 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 6, + /* 7 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 7, + /* 8 */ -1, /* One or more bits set in pending register 1 */ + /* 9 */ -2, /* One or more bits set in pending register 2 */ + /* 10 */ 7, /* GPU IRQ 7 */ + /* 11 */ 9, /* GPU IRQ 9 */ + /* 12 */ 10, /* GPU IRQ 10 */ + /* 13 */ 18, /* GPU IRQ 18 */ + /* 14 */ 19, /* GPU IRQ 19 */ + /* 15 */ 53, /* GPU IRQ 53 */ + /* 16 */ 54, /* GPU IRQ 54 */ + /* 17 */ 55, /* GPU IRQ 55 */ + /* 18 */ 56, /* GPU IRQ 56 */ + /* 19 */ 57, /* GPU IRQ 57 */ + /* 20 */ 62, /* GPU IRQ 62 */ +}; + +/* + * Define which basic peding register (BCM2835_IRQ_BASIC) bits + * should be processed through bcm2835_irq_speedup_table + */ + +#define BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS 0x1ffcff + +/* + * Determine the source of the interrupt and dispatch the correct handler. + */ +void bsp_interrupt_dispatch(void) +{ + unsigned int pend; + unsigned int pend_bit; + + rtems_vector_number vector = 255; + +#ifdef RTEMS_SMP + uint32_t cpu_index_self = _SMP_Get_current_processor(); + uint32_t local_source = BCM2835_REG(BCM2836_IRQ_SOURCE_REG(cpu_index_self)); + + if ( local_source & BCM2836_IRQ_SOURCE_MBOX3 ) { + /* reset mailbox 3 contents to zero */ + BCM2835_REG(BCM2836_MAILBOX_3_READ_CLEAR_BASE + 0x10 * cpu_index_self) = 0xffffffff; + _SMP_Inter_processor_interrupt_handler(); + } + if ( cpu_index_self != 0 ) + return; +#endif /* RTEMS_SMP */ + + pend = BCM2835_REG(BCM2835_IRQ_BASIC); + if ( pend & BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS ) { + pend_bit = ffs(pend) - 1; + vector = bcm2835_irq_speedup_table[pend_bit]; + } else { + pend = BCM2835_REG(BCM2835_IRQ_PENDING1); + if ( pend != 0 ) { + pend_bit = ffs(pend) - 1; + vector = pend_bit; + } else { + pend = BCM2835_REG(BCM2835_IRQ_PENDING2); + if ( pend != 0 ) { + pend_bit = ffs(pend) - 1; + vector = pend_bit + 32; + } + } + } + + if ( vector < 255 ) + { + bsp_interrupt_handler_dispatch(vector); + } +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + BCM2835_REG(bsp_vector_to_reg(vector)->enable_reg_addr) = + bsp_vector_to_mask(vector); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + BCM2835_REG(bsp_vector_to_reg(vector)->disable_reg_addr) = + bsp_vector_to_mask(vector); +} + +void bsp_interrupt_handler_default(rtems_vector_number vector) +{ + printk("spurious interrupt: %lu\n", vector); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + BCM2835_REG(BCM2835_IRQ_DISABLE1) = 0xffffffff; + BCM2835_REG(BCM2835_IRQ_DISABLE2) = 0xffffffff; + BCM2835_REG(BCM2835_IRQ_DISABLE_BASIC) = 0xffffffff; + BCM2835_REG(BCM2835_IRQ_FIQ_CTRL) = 0; + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/rtl22xx/irq/irq.c b/bsps/arm/rtl22xx/irq/irq.c new file mode 100644 index 0000000000..83e140bd7b --- /dev/null +++ b/bsps/arm/rtl22xx/irq/irq.c @@ -0,0 +1,70 @@ +/* + * Philps LPC22XX Interrupt handler + * + * Copyright (c) 2010 embedded brains GmbH. + * + * Copyright (c) 2006 by Ray<rayx.cn@gmail.com> to support LPC ARM + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/armv4.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> + +#include <lpc22xx.h> + +void bsp_interrupt_dispatch(void) +{ + rtems_vector_number vector = 31 - __builtin_clz(VICIRQStatus); + + bsp_interrupt_handler_dispatch(vector); + + VICVectAddr = 0; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + VICIntEnable |= 1 << vector; +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + VICIntEnClr = 1 << vector; +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + volatile uint32_t *ctrl = (volatile uint32_t *) VICVectCntlBase; + size_t i = 0; + + /* Disable all interrupts */ + VICIntEnClr = 0xffffffff; + + /* Use IRQ category */ + VICIntSelect = 0; + + /* Enable access in USER mode */ + VICProtection = 0; + + for (i = 0; i < 16; ++i) { + /* Disable vector mode */ + ctrl [i] = 0; + + /* Acknowledge interrupts for all priorities */ + VICVectAddr = 0; + } + + /* Acknowledge interrupts for all priorities */ + VICVectAddr = 0; + + /* Install the IRQ exception handler */ + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/shared/irq/irq-armv7m.c b/bsps/arm/shared/irq/irq-armv7m.c new file mode 100644 index 0000000000..99c0e373bf --- /dev/null +++ b/bsps/arm/shared/irq/irq-armv7m.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011-2012 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <string.h> + +#include <rtems/score/armv7m.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> +#include <bsp/armv7m-irq.h> + +#ifdef ARM_MULTILIB_ARCH_V7M + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + _ARMV7M_NVIC_Set_enable((int) vector); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + _ARMV7M_NVIC_Clear_enable((int) vector); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + int i; + ARMV7M_Exception_handler *vector_table = + (ARMV7M_Exception_handler *) bsp_vector_table_begin; + + if (bsp_vector_table_begin != bsp_start_vector_table_begin) { + memcpy( + vector_table, + bsp_start_vector_table_begin, + (size_t) bsp_vector_table_size + ); + } + + _ARMV7M_SCB->icsr = ARMV7M_SCB_ICSR_PENDSVCLR | ARMV7M_SCB_ICSR_PENDSTCLR; + + for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) { + vector_table [ARMV7M_VECTOR_IRQ(i)] = _ARMV7M_NVIC_Interrupt_dispatch; + _ARMV7M_NVIC_Clear_enable(i); + _ARMV7M_NVIC_Clear_pending(i); + _ARMV7M_NVIC_Set_priority(i, BSP_ARMV7M_IRQ_PRIORITY_DEFAULT); + } + + _ARMV7M_SCB->vtor = vector_table; + + return RTEMS_SUCCESSFUL; +} + +#endif /* ARM_MULTILIB_ARCH_V7M */ diff --git a/bsps/arm/shared/irq/irq-dispatch-armv7m.c b/bsps/arm/shared/irq/irq-dispatch-armv7m.c new file mode 100644 index 0000000000..c810a9784a --- /dev/null +++ b/bsps/arm/shared/irq/irq-dispatch-armv7m.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2011-2012 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/armv7m.h> + +#include <bsp/irq-generic.h> +#include <bsp/armv7m-irq.h> + +#ifdef ARM_MULTILIB_ARCH_V7M + +void _ARMV7M_NVIC_Interrupt_dispatch(void) +{ + rtems_vector_number vector = + ARMV7M_SCB_ICSR_VECTACTIVE_GET(_ARMV7M_SCB->icsr); + + _ARMV7M_Interrupt_service_enter(); + bsp_interrupt_handler_dispatch(ARMV7M_IRQ_OF_VECTOR(vector)); + _ARMV7M_Interrupt_service_leave(); +} + +#endif /* ARM_MULTILIB_ARCH_V7M */ diff --git a/bsps/arm/shared/irq/irq-gic.c b/bsps/arm/shared/irq/irq-gic.c new file mode 100644 index 0000000000..ea4b6ef06a --- /dev/null +++ b/bsps/arm/shared/irq/irq-gic.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/arm-gic.h> + +#include <rtems/score/armv4.h> + +#include <libcpu/arm-cp15.h> + +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/start.h> + +#define GIC_CPUIF ((volatile gic_cpuif *) BSP_ARM_GIC_CPUIF_BASE) + +#define PRIORITY_DEFAULT 127 + +void bsp_interrupt_dispatch(void) +{ + volatile gic_cpuif *cpuif = GIC_CPUIF; + uint32_t icciar = cpuif->icciar; + rtems_vector_number vector = GIC_CPUIF_ICCIAR_ACKINTID_GET(icciar); + rtems_vector_number spurious = 1023; + + if (vector != spurious) { + uint32_t psr = _ARMV4_Status_irq_enable(); + + bsp_interrupt_handler_dispatch(vector); + + _ARMV4_Status_restore(psr); + + cpuif->icceoir = icciar; + } +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + volatile gic_dist *dist = ARM_GIC_DIST; + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + gic_id_enable(dist, vector); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + volatile gic_dist *dist = ARM_GIC_DIST; + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + gic_id_disable(dist, vector); +} + +static inline uint32_t get_id_count(volatile gic_dist *dist) +{ + uint32_t id_count = GIC_DIST_ICDICTR_IT_LINES_NUMBER_GET(dist->icdictr); + + id_count = 32 * (id_count + 1); + id_count = id_count <= 1020 ? id_count : 1020; + + return id_count; +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + volatile gic_cpuif *cpuif = GIC_CPUIF; + volatile gic_dist *dist = ARM_GIC_DIST; + uint32_t id_count = get_id_count(dist); + uint32_t id; + + arm_cp15_set_exception_handler( + ARM_EXCEPTION_IRQ, + _ARMV4_Exception_interrupt + ); + + for (id = 0; id < id_count; id += 32) { + dist->icdicer[id / 32] = 0xffffffff; + } + + for (id = 0; id < id_count; ++id) { + gic_id_set_priority(dist, id, PRIORITY_DEFAULT); + } + + for (id = 32; id < id_count; ++id) { + gic_id_set_targets(dist, id, 0x01); + } + + cpuif->iccpmr = GIC_CPUIF_ICCPMR_PRIORITY(0xff); + cpuif->iccbpr = GIC_CPUIF_ICCBPR_BINARY_POINT(0x0); + cpuif->iccicr = GIC_CPUIF_ICCICR_ENABLE; + + dist->icddcr = GIC_DIST_ICDDCR_ENABLE; + + return RTEMS_SUCCESSFUL; +} + +#ifdef RTEMS_SMP +BSP_START_TEXT_SECTION void arm_gic_irq_initialize_secondary_cpu(void) +{ + volatile gic_cpuif *cpuif = GIC_CPUIF; + volatile gic_dist *dist = ARM_GIC_DIST; + + while ((dist->icddcr & GIC_DIST_ICDDCR_ENABLE) == 0) { + /* Wait */ + } + + cpuif->iccpmr = GIC_CPUIF_ICCPMR_PRIORITY(0xff); + cpuif->iccbpr = GIC_CPUIF_ICCBPR_BINARY_POINT(0x0); + cpuif->iccicr = GIC_CPUIF_ICCICR_ENABLE; +} +#endif + +rtems_status_code arm_gic_irq_set_priority( + rtems_vector_number vector, + uint8_t priority +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (bsp_interrupt_is_valid_vector(vector)) { + volatile gic_dist *dist = ARM_GIC_DIST; + + gic_id_set_priority(dist, vector, priority); + } else { + sc = RTEMS_INVALID_ID; + } + + return sc; +} + +rtems_status_code arm_gic_irq_get_priority( + rtems_vector_number vector, + uint8_t *priority +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (bsp_interrupt_is_valid_vector(vector)) { + volatile gic_dist *dist = ARM_GIC_DIST; + + *priority = gic_id_get_priority(dist, vector); + } else { + sc = RTEMS_INVALID_ID; + } + + return sc; +} + +void bsp_interrupt_set_affinity( + rtems_vector_number vector, + const Processor_mask *affinity +) +{ + volatile gic_dist *dist = ARM_GIC_DIST; + uint8_t targets = (uint8_t) _Processor_mask_To_uint32_t(affinity, 0); + + gic_id_set_targets(dist, vector, targets); +} + +void bsp_interrupt_get_affinity( + rtems_vector_number vector, + Processor_mask *affinity +) +{ + volatile gic_dist *dist = ARM_GIC_DIST; + uint8_t targets = gic_id_get_targets(dist, vector); + + _Processor_mask_From_uint32_t(affinity, targets, 0); +} diff --git a/bsps/arm/smdk2410/irq/irq.c b/bsps/arm/smdk2410/irq/irq.c new file mode 100644 index 0000000000..ea8f610353 --- /dev/null +++ b/bsps/arm/smdk2410/irq/irq.c @@ -0,0 +1,45 @@ +/* irq.c + * + * This file contains the implementation of the function described in irq.h + * + * Copyright (c) 2010 embedded brains GmbH. + * + * CopyRight (C) 2000 Canon Research France SA. + * Emmanuel Raguet, mailto:raguet@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/armv4.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> + +#include <s3c24xx.h> + +void bsp_interrupt_dispatch(void) +{ + rtems_vector_number vector = *((uint32_t *) rINTOFFSET_ADDR); + + bsp_interrupt_handler_dispatch(vector); +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/tms570/irq/irq.c b/bsps/arm/tms570/irq/irq.c new file mode 100644 index 0000000000..579c11ed2a --- /dev/null +++ b/bsps/arm/tms570/irq/irq.c @@ -0,0 +1,202 @@ +/** + * @file irq.c + * + * @ingroup tms570 + * + * @brief TMS570 interrupt support functions definitions. + */ + +/* + * Copyright (c) 2014 Premysl Houdek <kom541000@gmail.com> + * + * Google Summer of Code 2014 at + * Czech Technical University in Prague + * Zikova 1903/4 + * 166 36 Praha 6 + * Czech Republic + * + * Based on LPC24xx and LPC1768 BSP + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/irq-generic.h> +#include <bsp/tms570-vim.h> +#include <bsp/irq.h> +#include <rtems/score/armv4.h> + +unsigned int priorityTable[BSP_INTERRUPT_VECTOR_MAX+1]; + +/** + * @brief Set priority of the interrupt vector. + * + * This function is here because of compability. It should set + * priority of the interrupt vector. + * @warning It does not set any priority at HW layer. It is nearly imposible to + * @warning set priority of the interrupt on TMS570 in a nice way. + * @param[in] vector vector of isr + * @param[in] priority new priority assigned to the vector + * @return Void + */ +void tms570_irq_set_priority( + rtems_vector_number vector, + unsigned priority +) +{ + if ( bsp_interrupt_is_valid_vector(vector) ) { + priorityTable[vector] = priority; + } +} + +/** + * @brief Gets priority of the interrupt vector. + * + * This function is here because of compability. It returns priority + * of the isr vector last set by tms570_irq_set_priority function. + * + * @warning It does not return any real priority of the HW layer. + * @param[in] vector vector of isr + * @retval 0 vector is invalid. + * @retval priority priority of the interrupt + */ +unsigned tms570_irq_get_priority( + rtems_vector_number vector +) +{ + if ( bsp_interrupt_is_valid_vector(vector) ) { + return priorityTable[vector]; + } + return 0; +} + +/** + * @brief Interrupt dispatch + * + * Called by OS to determine which interrupt occured. + * Function passes control to interrupt handler. + * + * @return Void + */ +void bsp_interrupt_dispatch(void) +{ + rtems_vector_number vector = TMS570_VIM.IRQINDEX-1; + + bsp_interrupt_handler_dispatch(vector); +} + +/** + * @brief enables interrupt vector in the HW + * + * Enables HW interrupt for specified vector + * + * @param[in] vector vector of the isr which needs to be enabled. + * @retval RTEMS_INVALID_ID vector is invalid. + * @retval RTEMS_SUCCESSFUL interrupt source enabled. + */ +void bsp_interrupt_vector_enable( + rtems_vector_number vector +) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + TMS570_VIM.REQENASET[vector >> 5] = 1 << (vector & 0x1f); +} + +/** + * @brief disables interrupt vector in the HW + * + * Disables HW interrupt for specified vector + * + * @param[in] vector vector of the isr which needs to be disabled. + * @retval RTEMS_INVALID_ID vector is invalid. + * @retval RTEMS_SUCCESSFUL interrupt source disabled. + */ +void bsp_interrupt_vector_disable( + rtems_vector_number vector +) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + TMS570_VIM.REQENACLR[vector >> 5] = 1 << (vector & 0x1f); +} + +/** + * @brief Init function of interrupt module + * + * Resets vectored interrupt interface to default state. + * Disables all interrupts. + * Set all sources as IRQ (not FIR). + * + * @retval RTEMS_SUCCESSFUL All is set + */ +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + void (**vim_vec)(void) = (void (**)(void)) 0xFFF82000; + unsigned int value = 0x00010203; + unsigned int i = 0; + uint32_t sctlr; + + /* Disable interrupts */ + for ( i = 0; i < 3; i++ ) { + TMS570_VIM.REQENACLR[i] = 0xffffffff; + } + /* Map default events on interrupt vectors */ + for ( i = 0; i < 24; i += 1, value += 0x04040404) { + TMS570_VIM.CHANCTRL[i] = value; + } + /* Set all vectors as IRQ (not FIR) */ + TMS570_VIM.FIRQPR[0] = 3; + TMS570_VIM.FIRQPR[1] = 0; + TMS570_VIM.FIRQPR[2] = 0; + + /* + _CPU_ISR_install_vector( + ARM_EXCEPTION_IRQ, + _ARMV4_Exception_interrupt, + NULL + ); + + Call to setup of interrupt entry in CPU level exception vectors table + is not used (necessary/possible) because the table is provided + by c/src/lib/libbsp/arm/shared/start/start.S and POM overlay + solution remaps that to address zero. + */ + + for ( i = 0; i <= 94; ++i ) { + vim_vec[i] = _ARMV4_Exception_interrupt; + } + /* Clear bit VE in SCTLR register to not use VIM IRQ exception bypass*/ + asm volatile ("mrc p15, 0, %0, c1, c0, 0\n": "=r" (sctlr)); + /* + * Disable bypass of CPU level exception table for interrupt entry which + * can be provided by VIM hardware + */ + sctlr &= ~(1 << 24); + #if 0 + /* + * Option to enable exception table bypass for interrupts + * + * Because RTEMS requires all interrupts to be serviced through + * common _ARMV4_Exception_interrupt handler to allow task switching + * on exit from interrupt working correctly, vim_vec cannot point + * directly to individual vector handlers and need to point + * to single entry path. But if TMS570_VIM.IRQINDEX is then used + * to target execution to corresponding service then for some + * peripherals (i.e. EMAC) interrupt is already acknowledged + * by VIM and IRQINDEX is read as zero which leads to spurious + * interrupt and peripheral not serviced/blocked. + * + * To analyze this behavior we used trampolines which setup + * bsp_interrupt_vector_inject and pass execution to + * _ARMV4_Exception_interrupt. It works but is more ugly than + * use of POM remap for these cases where application does not + * start at address 0x00000000. If RTEMS image is placed at + * memory space beginning then no of these constructs is necessary. + */ + sctlr |= 1 << 24; + #endif + asm volatile ("mcr p15, 0, %0, c1, c0, 0\n": : "r" (sctlr)); + + return RTEMS_SUCCESSFUL; +} |