From 5df9bf6e8a8f1efa88625467d9ccf4ac51d89cdb Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 5 Dec 2013 16:42:06 +0100 Subject: bsp/genmcf548x: Add interrupt extension support --- c/src/lib/libbsp/m68k/genmcf548x/Makefile.am | 14 ++ c/src/lib/libbsp/m68k/genmcf548x/include/irq.h | 79 +++++++++ c/src/lib/libbsp/m68k/genmcf548x/irq/irq.c | 235 +++++++++++++++++++++++++ c/src/lib/libbsp/m68k/genmcf548x/preinstall.am | 12 ++ 4 files changed, 340 insertions(+) create mode 100644 c/src/lib/libbsp/m68k/genmcf548x/include/irq.h create mode 100644 c/src/lib/libbsp/m68k/genmcf548x/irq/irq.c (limited to 'c/src/lib/libbsp/m68k/genmcf548x') diff --git a/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am b/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am index 6a7cfd9faa..64e768210c 100644 --- a/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am +++ b/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am @@ -9,6 +9,12 @@ include_HEADERS += include/tm27.h nodist_include_HEADERS = include/bspopts.h nodist_include_bsp_HEADERS = ../../shared/include/bootcard.h + +include_bsp_HEADERS = +include_bsp_HEADERS += ../../shared/include/irq-generic.h +include_bsp_HEADERS += ../../shared/include/irq-info.h +include_bsp_HEADERS += include/irq.h + DISTCLEANFILES = include/bspopts.h noinst_PROGRAMS = @@ -42,6 +48,14 @@ libbsp_a_SOURCES += console/console.c # timer libbsp_a_SOURCES += timer/timer.c +# IRQ +libbsp_a_SOURCES += ../../shared/src/irq-default-handler.c +libbsp_a_SOURCES += ../../shared/src/irq-info.c +libbsp_a_SOURCES += ../../shared/src/irq-legacy.c +libbsp_a_SOURCES += ../../shared/src/irq-server.c +libbsp_a_SOURCES += ../../shared/src/irq-shell.c +libbsp_a_SOURCES += irq/irq.c + if HAS_NETWORKING network_CPPFLAGS = -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ noinst_PROGRAMS += network.rel diff --git a/c/src/lib/libbsp/m68k/genmcf548x/include/irq.h b/c/src/lib/libbsp/m68k/genmcf548x/include/irq.h new file mode 100644 index 0000000000..23ff73d46f --- /dev/null +++ b/c/src/lib/libbsp/m68k/genmcf548x/include/irq.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * 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. + */ + +#ifndef LIBBSP_M68K_MCF548X_IRQ_H +#define LIBBSP_M68K_MCF548X_IRQ_H + +#include +#include +#include + +#define MCF548X_IRQ_EPORT_EPF1 1 +#define MCF548X_IRQ_EPORT_EPF2 2 +#define MCF548X_IRQ_EPORT_EPF3 3 +#define MCF548X_IRQ_EPORT_EPF4 4 +#define MCF548X_IRQ_EPORT_EPF5 5 +#define MCF548X_IRQ_EPORT_EPF6 6 +#define MCF548X_IRQ_EPORT_EPF7 7 +#define MCF548X_IRQ_USB_EP0ISR 15 +#define MCF548X_IRQ_USB_EP1ISR 16 +#define MCF548X_IRQ_USB_EP2ISR 17 +#define MCF548X_IRQ_USB_EP3ISR 18 +#define MCF548X_IRQ_USB_EP4ISR 19 +#define MCF548X_IRQ_USB_EP5ISR 20 +#define MCF548X_IRQ_USB_EP6ISR 21 +#define MCF548X_IRQ_USB_ISR 22 +#define MCF548X_IRQ_USB_AISR 23 +#define MCF548X_IRQ_DSPI_RFOF_TFUF 25 +#define MCF548X_IRQ_DSPI_RFOF 26 +#define MCF548X_IRQ_DSPI_RFDF 27 +#define MCF548X_IRQ_DSPI_TFUF 28 +#define MCF548X_IRQ_DSPI_TCF 29 +#define MCF548X_IRQ_DSPI_TFFF 30 +#define MCF548X_IRQ_DSPI_EOQF 31 +#define MCF548X_IRQ_DSPI 25 +#define MCF548X_IRQ_PSC3 32 +#define MCF548X_IRQ_PSC2 33 +#define MCF548X_IRQ_PSC1 34 +#define MCF548X_IRQ_PSC0 35 +#define MCF548X_IRQ_PSC(i) (35 - (i)) +#define MCF548X_IRQ_COMMTIM 36 +#define MCF548X_IRQ_SEC 37 +#define MCF548X_IRQ_FEC1 38 +#define MCF548X_IRQ_FEC0 39 +#define MCF548X_IRQ_FEC(i) (39 - (i)) +#define MCF548X_IRQ_I2C 40 +#define MCF548X_IRQ_PCIARB 41 +#define MCF548X_IRQ_CBPCI 42 +#define MCF548X_IRQ_XLBPCI 43 +#define MCF548X_IRQ_XLBARB 47 +#define MCF548X_IRQ_DMA 48 +#define MCF548X_IRQ_CAN0_ERROR 49 +#define MCF548X_IRQ_CAN0_BUSOFF 50 +#define MCF548X_IRQ_CAN0_MBOR 51 +#define MCF548X_IRQ_SLT1 53 +#define MCF548X_IRQ_SLT0 54 +#define MCF548X_IRQ_CAN1_ERROR 55 +#define MCF548X_IRQ_CAN1_BUSOFF 56 +#define MCF548X_IRQ_CAN1_MBOR 57 +#define MCF548X_IRQ_GPT3 59 +#define MCF548X_IRQ_GPT2 60 +#define MCF548X_IRQ_GPT1 61 +#define MCF548X_IRQ_GPT0 62 + +#define BSP_INTERRUPT_VECTOR_MIN 1 + +#define BSP_INTERRUPT_VECTOR_MAX 63 + +#endif /* LIBBSP_M68K_MCF548X_IRQ_H */ diff --git a/c/src/lib/libbsp/m68k/genmcf548x/irq/irq.c b/c/src/lib/libbsp/m68k/genmcf548x/irq/irq.c new file mode 100644 index 0000000000..2f2f43a7cc --- /dev/null +++ b/c/src/lib/libbsp/m68k/genmcf548x/irq/irq.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * 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. + */ + +#include + +#include + +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; +} + +rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (bsp_interrupt_is_valid_vector(vector)) { + volatile uint32_t *imr = vector_to_imr(vector); + uint32_t bit = vector_to_bit(vector); + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + *imr &= ~bit; + rtems_interrupt_enable(level); + } else { + sc = RTEMS_INVALID_ID; + } + + return sc; +} + +rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (bsp_interrupt_is_valid_vector(vector)) { + volatile uint32_t *imr = vector_to_imr(vector); + uint32_t bit = vector_to_bit(vector); + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + *imr |= bit; + rtems_interrupt_enable(level); + } else { + sc = RTEMS_INVALID_ID; + } + + return sc; +} + +static void_func get_exception_handler(rtems_vector_number vector) +{ + void_func *exception_table; + + m68k_get_vbr(exception_table); + + return exception_table[vector_to_exception_vector(vector)]; +} + +static void set_exception_handler(rtems_vector_number vector, void_func handler) +{ + void_func *exception_table; + + m68k_get_vbr(exception_table); + + 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; +} diff --git a/c/src/lib/libbsp/m68k/genmcf548x/preinstall.am b/c/src/lib/libbsp/m68k/genmcf548x/preinstall.am index 8c86e37d70..31ce6bc0ca 100644 --- a/c/src/lib/libbsp/m68k/genmcf548x/preinstall.am +++ b/c/src/lib/libbsp/m68k/genmcf548x/preinstall.am @@ -49,6 +49,18 @@ $(PROJECT_INCLUDE)/bsp/bootcard.h: ../../shared/include/bootcard.h $(PROJECT_INC $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/bootcard.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/bootcard.h +$(PROJECT_INCLUDE)/bsp/irq-generic.h: ../../shared/include/irq-generic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-generic.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-generic.h + +$(PROJECT_INCLUDE)/bsp/irq-info.h: ../../shared/include/irq-info.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-info.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-info.h + +$(PROJECT_INCLUDE)/bsp/irq.h: include/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h + $(PROJECT_INCLUDE)/coverhd.h: ../../shared/include/coverhd.h $(PROJECT_INCLUDE)/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/coverhd.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/coverhd.h -- cgit v1.2.3