summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/virtex/irq/irq_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/powerpc/virtex/irq/irq_init.c')
-rw-r--r--bsps/powerpc/virtex/irq/irq_init.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/bsps/powerpc/virtex/irq/irq_init.c b/bsps/powerpc/virtex/irq/irq_init.c
new file mode 100644
index 0000000000..55194cb1e6
--- /dev/null
+++ b/bsps/powerpc/virtex/irq/irq_init.c
@@ -0,0 +1,167 @@
+/*===============================================================*\
+| Project: RTEMS virtex BSP |
++-----------------------------------------------------------------+
+| Partially based on the code references which are named below. |
+| Adaptions, modifications, enhancements and any recent parts of |
+| the code are: |
+| 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.org/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the irq controller handler |
+\*===============================================================*/
+
+/* Content moved from opbintctrl.c:
+ *
+ * This file contains definitions and declarations for the
+ * Xilinx Off Processor Bus (OPB) Interrupt Controller
+ *
+ * Author: Keith Robertson <kjrobert@alumni.uwaterloo.ca>
+ * COPYRIGHT (c) 2005 Linn Products Ltd, Scotland.
+ *
+ * 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>
+#include <bsp/irq-generic.h>
+#include <bsp/vectors.h>
+
+#include <libcpu/powerpc-utility.h>
+
+/*
+ * Acknowledge a mask of interrupts.
+ */
+static void set_iar(uint32_t mask)
+{
+ *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_IAR)) = mask;
+}
+
+/*
+ * Set IER state. Used to (dis)enable a mask of vectors.
+ * If you only have to do one, use enable/disable_vector.
+ */
+static void set_ier(uint32_t mask)
+{
+ *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_IER)) = mask;
+}
+
+/*
+ * Retrieve contents of Interrupt Pending Register
+ */
+static uint32_t get_ipr(void)
+{
+ uint32_t c = *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_IPR));
+ return c;
+}
+
+static void BSP_irq_enable_at_opbintc (rtems_irq_number irqnum)
+{
+ *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_SIE))
+ = 1 << (irqnum - BSP_OPBINTC_IRQ_LOWEST_OFFSET);
+}
+
+static void BSP_irq_disable_at_opbintc (rtems_irq_number irqnum)
+{
+ *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_CIE))
+ = 1 << (irqnum - BSP_OPBINTC_IRQ_LOWEST_OFFSET);
+}
+
+/*
+ * IRQ Handler: this is called from the primary exception dispatcher
+ */
+static void BSP_irq_handle_at_opbintc(void)
+{
+ uint32_t ipr;
+
+ /* Get pending interrupts */
+ ipr = get_ipr();
+
+ if (ipr != 0) {
+ /* Acknowledge all pending interrupts now and service them afterwards */
+ set_iar(ipr);
+
+ do {
+ /* Get highest priority pending interrupt */
+ uint32_t i = 31 - ppc_count_leading_zeros(ipr);
+
+ ipr &= ~(1U << i);
+
+ bsp_interrupt_handler_dispatch(i+BSP_OPBINTC_IRQ_LOWEST_OFFSET);
+ } while (ipr != 0);
+ }
+}
+
+/*
+ * activate the interrupt controller
+ */
+static void opb_intc_init(void)
+{
+ uint32_t i, mask = 0;
+
+ /* mask off all interrupts */
+ set_ier(0x0);
+
+ for (i = 0; i < OPB_INTC_IRQ_MAX; i++) {
+ mask |= (1 << i);
+ }
+
+ /* make sure interupt status register is clear before we enable the interrupt controller */
+ *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_ISR)) = 0;
+
+ /* acknowledge all interrupt sources */
+ set_iar(mask);
+
+ /* Turn on normal hardware operation of interrupt controller */
+ *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_MER)) =
+ (OPB_INTC_MER_HIE);
+
+ /* Enable master interrupt switch for the interrupt controller */
+ *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_MER)) =
+ (OPB_INTC_MER_HIE | OPB_INTC_MER_ME);
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ if (BSP_IS_OPBINTC_IRQ(vector)) {
+ BSP_irq_enable_at_opbintc(vector);
+ }
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ if (BSP_IS_OPBINTC_IRQ(vector)) {
+ BSP_irq_disable_at_opbintc(vector);
+ }
+}
+
+static int C_dispatch_irq_handler(BSP_Exception_frame *frame, unsigned int excNum)
+{
+ BSP_irq_handle_at_opbintc();
+
+ return 0;
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ opb_intc_init();
+
+ ppc_exc_set_handler(ASM_EXT_VECTOR, C_dispatch_irq_handler);
+
+ return RTEMS_SUCCESSFUL;
+}