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/m68k | |
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/m68k')
-rw-r--r-- | bsps/m68k/genmcf548x/irq/intc-icr-init-values.c | 29 | ||||
-rw-r--r-- | bsps/m68k/genmcf548x/irq/irq.c | 229 |
2 files changed, 258 insertions, 0 deletions
diff --git a/bsps/m68k/genmcf548x/irq/intc-icr-init-values.c b/bsps/m68k/genmcf548x/irq/intc-icr-init-values.c new file mode 100644 index 0000000000..afc58224ea --- /dev/null +++ b/bsps/m68k/genmcf548x/irq/intc-icr-init-values.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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 <bsp.h> +#include <bsp/irq.h> + +#define ICR(lvl, prio) (MCF548X_INTC_ICRn_IL(lvl) | MCF548X_INTC_ICRn_IP(prio)) + +const uint8_t mcf548x_intc_icr_init_values[64] = { + [MCF548X_IRQ_SLT0] = ICR(4, 7), + [MCF548X_IRQ_SLT1] = ICR(4, 6), + [MCF548X_IRQ_PSC0] = ICR(3, 7), + [MCF548X_IRQ_PSC1] = ICR(3, 6), + [MCF548X_IRQ_PSC2] = ICR(3, 5), + [MCF548X_IRQ_PSC3] = ICR(3, 4), + [MCF548X_IRQ_FEC0] = ICR(2, 7), + [MCF548X_IRQ_FEC1] = ICR(2, 6) +}; diff --git a/bsps/m68k/genmcf548x/irq/irq.c b/bsps/m68k/genmcf548x/irq/irq.c new file mode 100644 index 0000000000..f02231b67c --- /dev/null +++ b/bsps/m68k/genmcf548x/irq/irq.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 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 <bsp/irq-generic.h> + +#include <mcf548x/mcf548x.h> + +void asm_default_interrupt(void); + +typedef void (*void_func)(void); + +typedef struct { + rtems_interrupt_handler handler; + void *arg; + const char *info; +} interrupt_control; + +static interrupt_control interrupt_controls[BSP_INTERRUPT_VECTOR_MAX + 1]; + +static uint32_t vector_to_reg(rtems_vector_number vector) +{ + return ((vector + 32U) >> 5) & 0x1; +} + +static uint32_t vector_to_bit(rtems_vector_number vector) +{ + return 1U << (vector & 0x1fU); +} + +static volatile uint32_t *vector_to_imr(rtems_vector_number vector) +{ + volatile uint32_t *imr = &MCF548X_INTC_IMRH; + + return &imr[vector_to_reg(vector)]; +} + +static rtems_vector_number exception_vector_to_vector( + rtems_vector_number exception_vector +) +{ + return exception_vector - 64U; +} + +static rtems_vector_number vector_to_exception_vector( + rtems_vector_number vector +) +{ + return vector + 64U; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + volatile uint32_t *imr = vector_to_imr(vector); + uint32_t bit = vector_to_bit(vector); + rtems_interrupt_level level; + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + rtems_interrupt_disable(level); + *imr &= ~bit; + rtems_interrupt_enable(level); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + volatile uint32_t *imr = vector_to_imr(vector); + uint32_t bit = vector_to_bit(vector); + rtems_interrupt_level level; + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + rtems_interrupt_disable(level); + *imr |= bit; + rtems_interrupt_enable(level); +} + +static void_func get_exception_handler(rtems_vector_number vector) +{ + void **vbr; + void_func *exception_table; + + m68k_get_vbr(vbr); + + exception_table = (void_func *)vbr; + + return exception_table[vector_to_exception_vector(vector)]; +} + +static void set_exception_handler(rtems_vector_number vector, void_func handler) +{ + void **vbr; + void_func *exception_table; + + m68k_get_vbr(vbr); + + exception_table = (void_func *)vbr; + + exception_table[vector_to_exception_vector(vector)] = handler; +} + +static void dispatch_handler(rtems_vector_number exception_vector) +{ + const interrupt_control *ic = + &interrupt_controls[exception_vector_to_vector(exception_vector)]; + + (*ic->handler)(ic->arg); +} + +static uint8_t get_intc_icr(rtems_vector_number vector) +{ + volatile uint8_t *icr = &MCF548X_INTC_ICR0; + + return icr[vector]; +} + +rtems_status_code rtems_interrupt_handler_install( + rtems_vector_number vector, + const char *info, + rtems_option options, + rtems_interrupt_handler handler, + void *arg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (bsp_interrupt_is_valid_vector(vector)) { + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + + if ( + get_exception_handler(vector) == asm_default_interrupt + && get_intc_icr(vector) != 0 + ) { + interrupt_control *ic = &interrupt_controls[vector]; + + ic->handler = handler; + ic->arg = arg; + ic->info = info; + + _ISR_Vector_table[vector_to_exception_vector(vector)] + = dispatch_handler; + set_exception_handler(vector, _ISR_Handler); + bsp_interrupt_vector_enable(vector); + } else { + sc = RTEMS_RESOURCE_IN_USE; + } + + rtems_interrupt_enable(level); + } else { + sc = RTEMS_INVALID_ID; + } + + return sc; +} + +static bool is_occupied_by_us(rtems_vector_number vector) +{ + return get_exception_handler(vector) == _ISR_Handler + && _ISR_Vector_table[vector_to_exception_vector(vector)] + == dispatch_handler; +} + +rtems_status_code rtems_interrupt_handler_remove( + rtems_vector_number vector, + rtems_interrupt_handler handler, + void *arg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (bsp_interrupt_is_valid_vector(vector)) { + rtems_interrupt_level level; + interrupt_control *ic = &interrupt_controls[vector]; + + rtems_interrupt_disable(level); + + if ( + is_occupied_by_us(vector) + && ic->handler == handler + && ic->arg == arg + ) { + bsp_interrupt_vector_disable(vector); + set_exception_handler(vector, asm_default_interrupt); + + memset(ic, 0, sizeof(*ic)); + } else { + sc = RTEMS_UNSATISFIED; + } + + rtems_interrupt_enable(level); + } else { + sc = RTEMS_INVALID_ID; + } + + return sc; +} + +rtems_status_code rtems_interrupt_handler_iterate( + rtems_vector_number vector, + rtems_interrupt_per_handler_routine routine, + void *arg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (bsp_interrupt_is_valid_vector(vector)) { + if (is_occupied_by_us(vector)) { + const interrupt_control *ic = &interrupt_controls[vector]; + + (*routine)(arg, ic->info, RTEMS_INTERRUPT_UNIQUE, ic->handler, ic->arg); + } + } else { + sc = RTEMS_INVALID_ID; + } + + return sc; +} |