summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/powerpc/ppc403
diff options
context:
space:
mode:
authorThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2007-07-04 12:37:36 +0000
committerThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2007-07-04 12:37:36 +0000
commit862c231785024acbd6c830fb30e0a6a64e6c3318 (patch)
treefc09530e45e5436192c6286e70b912fbff8bcf16 /c/src/lib/libcpu/powerpc/ppc403
parentmerged individual exception handler code to a common one. (diff)
downloadrtems-862c231785024acbd6c830fb30e0a6a64e6c3318.tar.bz2
added virtex BSP support and some missing files for common PPC
exception handling
Diffstat (limited to 'c/src/lib/libcpu/powerpc/ppc403')
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.c292
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.h95
2 files changed, 387 insertions, 0 deletions
diff --git a/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.c b/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.c
new file mode 100644
index 0000000000..6a1f810cd0
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.c
@@ -0,0 +1,292 @@
+/* ictrl.c
+ *
+ * This routine installs and handles external interrupt vectors for
+ * PowerPC 403 CPU built-in external interrupt controller
+ *
+ * Author: Thomas Doerfler <td@imd.m.isar.de>
+ *
+ * COPYRIGHT (c) 1998 by IMD, Puchheim, Germany
+ *
+ * To anyone who acknowledges that this file is provided "AS IS"
+ * without any express or implied warranty:
+ * permission to use, copy, modify, and distribute this file
+ * for any purpose is hereby granted without fee, provided that
+ * the above copyright notice and this notice appears in all
+ * copies, and that the name of IMD not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * IMD makes no representations about the suitability
+ * of this software for any purpose.
+ *
+ * Modifications for PPC405GP by Dennis Ehlin
+ *
+ */
+
+#include "ictrl.h"
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include <stdlib.h> /* for atexit() */
+
+/*
+ * ISR vector table to dispatch external interrupts
+ */
+
+rtems_isr_entry ictrl_vector_table[PPC_IRQ_EXT_MAX];
+
+/*
+ *
+ * some utilities to access the EXI* registers
+ *
+ */
+
+/*
+ * clear bits in EXISR that have a bit set in mask
+ */
+#if defined(ppc405)
+RTEMS_INLINE_ROUTINE void
+clr_exisr(uint32_t mask)
+{
+ asm volatile ("mtdcr 0xC0,%0"::"r" (mask));/*EXISR*/
+}
+
+/*
+ * get value of EXISR
+ */
+RTEMS_INLINE_ROUTINE uint32_t
+get_exisr(void)
+{
+ uint32_t val;
+
+ asm volatile ("mfdcr %0,0xC0":"=r" (val));/*EXISR*/
+ return val;
+}
+
+/*
+ * get value of EXIER
+ */
+RTEMS_INLINE_ROUTINE uint32_t
+get_exier(void)
+{
+ uint32_t val;
+ asm volatile ("mfdcr %0,0xC2":"=r" (val));/*EXIER*/
+ return val;
+}
+
+/*
+ * set value of EXIER
+ */
+RTEMS_INLINE_ROUTINE void
+set_exier(uint32_t val)
+{
+ asm volatile ("mtdcr 0xC2,%0"::"r" (val));/*EXIER*/
+}
+
+#else /* not ppc405 */
+
+RTEMS_INLINE_ROUTINE void
+clr_exisr(uint32_t mask)
+{
+ asm volatile ("mtdcr 0x40,%0"::"r" (mask));/*EXISR*/
+}
+
+/*
+ * get value of EXISR
+ */
+RTEMS_INLINE_ROUTINE uint32_t
+get_exisr(void)
+{
+ uint32_t val;
+
+ asm volatile ("mfdcr %0,0x40":"=r" (val));/*EXISR*/
+ return val;
+}
+
+/*
+ * get value of EXIER
+ */
+RTEMS_INLINE_ROUTINE uint32_t
+get_exier(void)
+{
+ uint32_t val;
+ asm volatile ("mfdcr %0,0x42":"=r" (val));/*EXIER*/
+ return val;
+}
+
+/*
+ * set value of EXIER
+ */
+RTEMS_INLINE_ROUTINE void
+set_exier(uint32_t val)
+{
+ asm volatile ("mtdcr 0x42,%0"::"r" (val));/*EXIER*/
+}
+#endif /* ppc405 */
+/*
+ * enable an external interrupt, make this interrupt consistent
+ */
+RTEMS_INLINE_ROUTINE void
+enable_ext_irq( uint32_t mask)
+{
+ uint32_t isrlvl;
+ _CPU_ISR_Disable(isrlvl);
+ set_exier(get_exier() | ((mask)&PPC_EXI_MASK));
+ _CPU_ISR_Enable(isrlvl);
+}
+
+/*
+ * disable an external interrupt, make this interrupt consistent
+ */
+RTEMS_INLINE_ROUTINE void
+disable_ext_irq( uint32_t mask)
+{
+ uint32_t isrlvl;
+ _CPU_ISR_Disable(isrlvl);
+ set_exier(get_exier() & ~(mask) & PPC_EXI_MASK);
+ _CPU_ISR_Enable(isrlvl);
+}
+
+/*
+ *
+ * this function is called, when a external interrupt is present and
+ * enabled but there is no handler installed. It will clear
+ * the corresponding enable bits and call the spurious handler
+ * present in the CPU Configuration Table, if any.
+ *
+ */
+void
+ictrl_spurious_handler(uint32_t spurious_mask,
+ CPU_Interrupt_frame *cpu_frame)
+{
+ int v;
+
+ for (v=0; v < PPC_IRQ_EXT_MAX; v++) {
+ if (VEC_TO_EXMSK(v) & spurious_mask) {
+ clr_exisr(VEC_TO_EXMSK(v));
+ disable_ext_irq(VEC_TO_EXMSK(v));
+#if 0
+ printf("spurious external interrupt: %d at pc 0x%x; disabling\n",
+ vector, cpu_frame->Interrupt.pcoqfront);
+#endif
+ if (rtems_cpu_configuration_get_spurious_handler()) {
+ rtems_cpu_configuration_get_spurious_handler()(v + PPC_IRQ_EXT_BASE,cpu_frame);
+ }
+ }
+ }
+}
+
+
+/*
+ * ISR Handler: this is called from the primary exception dispatcher
+ */
+
+void
+ictrl_isr(rtems_vector_number vector,CPU_Interrupt_frame *cpu_frame)
+{
+ uint32_t istat,
+ mask,
+ global_vec;
+ int exvec;
+ rtems_isr_entry handler;
+
+ istat = get_exisr() & get_exier() & PPC_EXI_MASK;
+
+ /* FIXME: this may be speeded up using cntlzw instruction */
+ for (exvec = 0;exvec < PPC_IRQ_EXT_MAX;exvec++) {
+ mask = VEC_TO_EXMSK(exvec);
+ if (0 != (istat & mask)) {
+ /*clr_exisr(mask); too early to ack*/
+ handler = ictrl_vector_table[exvec];
+ if (handler) {
+ istat &= ~mask;
+ global_vec = exvec + PPC_IRQ_EXT_BASE;
+ (handler)(global_vec);
+ }
+ clr_exisr(mask);/* now we can ack*/
+ }
+ }
+ if (istat != 0) { /* anything left? then we have a spurious interrupt */
+ ictrl_spurious_handler(istat,cpu_frame);
+ }
+}
+
+/*
+ *
+ * the following functions form the user interface
+ *
+ */
+
+/*
+ *
+ * install a user vector for one of the external interrupt sources
+ *
+ */
+rtems_status_code
+ictrl_set_vector(rtems_isr_entry new_handler,
+ uint32_t vector,
+ rtems_isr_entry *old_handler
+)
+{
+ /*
+ * We put the actual user ISR address in 'ictrl_vector_table'. This will
+ * be used by the _ictrl_isr so the user gets control.
+ */
+
+ /* check for valid vector range */
+ if ((vector >= PPC_IRQ_EXT_BASE) &&
+ (vector < PPC_IRQ_EXT_BASE + PPC_IRQ_EXT_MAX)) {
+ /* return old handler entry */
+ *old_handler = ictrl_vector_table[vector - PPC_IRQ_EXT_BASE];
+
+ if (new_handler != NULL) {
+ /* store handler function... */
+ ictrl_vector_table[vector - PPC_IRQ_EXT_BASE] = new_handler;
+ /* then enable it in EXIER register */
+ enable_ext_irq(VEC_TO_EXMSK(vector - PPC_IRQ_EXT_BASE));
+ }
+ else { /* new_handler == NULL */
+ /* then disable it in EXIER register */
+ disable_ext_irq(VEC_TO_EXMSK(vector - PPC_IRQ_EXT_BASE));
+ ictrl_vector_table[vector - PPC_IRQ_EXT_BASE] = NULL;
+ }
+ return RTEMS_SUCCESSFUL;
+ }
+ else {
+ return RTEMS_INVALID_NUMBER;
+ }
+}
+
+/*
+ * Called via atexit()
+ * deactivate the interrupt controller
+ */
+
+void
+ictrl_exit(void)
+{
+ /* mark them all unused */
+ disable_ext_irq(~0);
+ clr_exisr(~0);
+
+}
+
+/*
+ * activate the interrupt controller
+ */
+
+rtems_status_code
+ictrl_init(void)
+{
+ proc_ptr dummy;
+
+ /* mark them all unused */
+ disable_ext_irq(~0);
+ clr_exisr(~0);
+
+ /* install the external interrupt handler */
+ _CPU_ISR_install_vector(PPC_IRQ_EXTERNAL,
+ ictrl_isr,
+ &dummy);
+ atexit(ictrl_exit);
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.h b/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.h
new file mode 100644
index 0000000000..4370788108
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.h
@@ -0,0 +1,95 @@
+/* ictrl.h
+ *
+ * This file contains definitions and declarations for the
+ * PowerPC 403 CPU built-in external interrupt controller
+ *
+ *
+ * Author: Thomas Doerfler <td@imd.m.isar.de>
+ *
+ * COPYRIGHT (c) 1998 by IMD, Puchheim, Germany
+ *
+ * To anyone who acknowledges that this file is provided "AS IS"
+ * without any express or implied warranty:
+ * permission to use, copy, modify, and distribute this file
+ * for any purpose is hereby granted without fee, provided that
+ * the above copyright notice and this notice appears in all
+ * copies, and that the name of IMD not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * IMD makes no representations about the suitability
+ * of this software for any purpose.
+ *
+ * Modifications for PPC405GP by Dennis Ehlin
+ *
+ */
+
+
+#ifndef _ICTRL_H
+#define _ICTRL_H
+
+#include <rtems.h>
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * definitions for second level IRQ handler support
+ * External Interrupts via EXTERNAL/EISR
+ */
+#define PPC_IRQ_EXT_BASE (PPC_IRQ_LAST+1)
+
+/* mask for external interrupt status in EXIER/EXISR register */
+/* note: critical interrupt is in these registers aswell */
+#ifndef ppc405
+#define PPC_EXI_MASK 0x0FFFFFFF
+#else /* ppc405 */
+#define PPC_EXI_MASK 0xFFFFFFFF
+#endif /* ppc405 */
+
+#ifndef ppc405
+#define PPC_IRQ_EXT_SPIR (PPC_IRQ_EXT_BASE+4)
+#define PPC_IRQ_EXT_SPIT (PPC_IRQ_EXT_BASE+5)
+#else /* ppc405 */
+#define PPC_IRQ_EXT_UART0 (PPC_IRQ_EXT_BASE+0)
+#define PPC_IRQ_EXT_UART1 (PPC_IRQ_EXT_BASE+1)
+#endif /* ppc405 */
+#define PPC_IRQ_EXT_JTAGR (PPC_IRQ_EXT_BASE+6)
+#define PPC_IRQ_EXT_JTAGT (PPC_IRQ_EXT_BASE+7)
+#define PPC_IRQ_EXT_DMA0 (PPC_IRQ_EXT_BASE+8)
+#define PPC_IRQ_EXT_DMA1 (PPC_IRQ_EXT_BASE+9)
+#define PPC_IRQ_EXT_DMA2 (PPC_IRQ_EXT_BASE+10)
+#define PPC_IRQ_EXT_DMA3 (PPC_IRQ_EXT_BASE+11)
+#define PPC_IRQ_EXT_0 (PPC_IRQ_EXT_BASE+27)
+#define PPC_IRQ_EXT_1 (PPC_IRQ_EXT_BASE+28)
+#define PPC_IRQ_EXT_2 (PPC_IRQ_EXT_BASE+29)
+#define PPC_IRQ_EXT_3 (PPC_IRQ_EXT_BASE+30)
+#define PPC_IRQ_EXT_4 (PPC_IRQ_EXT_BASE+31)
+
+#define PPC_IRQ_EXT_MAX (32)
+
+#define VEC_TO_EXMSK(v) (0x80000000 >> (v))
+
+/*
+ *
+ * install a user vector for one of the external interrupt sources
+ *
+ */
+rtems_status_code
+ictrl_set_vector(rtems_isr_entry new_handler,
+ uint32_t vector,
+ rtems_isr_entry *old_handler
+);
+/*
+ * activate the interrupt controller
+ */
+rtems_status_code
+ictrl_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ICTRL_H */
+/* end of include file */