summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/powerpc/mpc5xx/irq/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libcpu/powerpc/mpc5xx/irq/irq.c')
-rw-r--r--c/src/lib/libcpu/powerpc/mpc5xx/irq/irq.c463
1 files changed, 0 insertions, 463 deletions
diff --git a/c/src/lib/libcpu/powerpc/mpc5xx/irq/irq.c b/c/src/lib/libcpu/powerpc/mpc5xx/irq/irq.c
deleted file mode 100644
index 8bb3cd240e..0000000000
--- a/c/src/lib/libcpu/powerpc/mpc5xx/irq/irq.c
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * This file contains the implementation of the function described in irq.h
- */
-
-/*
- * MPC5xx port sponsored by Defence Research and Development Canada - Suffield
- * Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
- *
- * Derived from libbsp/powerpc/mbx8xx/irq/irq.c:
- *
- * Copyright (C) 1998, 1999 valette@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.h>
-#include <mpc5xx.h>
-#include <libcpu/vectors.h>
-#include <libcpu/raw_exception.h>
-#include <libcpu/irq.h>
-#include <bsp/irq.h>
-
-/*
- * Convert an rtems_irq_number constant to an interrupt level
- * suitable for programming into an I/O device's interrupt level field.
- */
-int CPU_irq_level_from_symbolic_name(const rtems_irq_number name)
-{
- if (CPU_USIU_EXT_IRQ_0 <= name && name <= CPU_USIU_INT_IRQ_7)
- return (name - CPU_USIU_EXT_IRQ_0) / 2;
-
- if (CPU_UIMB_IRQ_8 <= name && name <= CPU_UIMB_IRQ_31)
- return 8 + (name - CPU_UIMB_IRQ_8);
-
- return 31; /* reasonable default */
-}
-
-/*
- * default handler connected on each irq after bsp initialization
- */
-static rtems_irq_connect_data default_rtems_entry;
-
-/*
- * location used to store initial tables used for interrupt
- * management.
- */
-static rtems_irq_global_settings* internal_config;
-static rtems_irq_connect_data* rtems_hdl_tbl;
-
-/*
- * Check if symbolic IRQ name is an USIU IRQ
- */
-static inline int is_usiu_irq(const rtems_irq_number irqLine)
-{
- return (((int) irqLine <= CPU_USIU_IRQ_MAX_OFFSET) &&
- ((int) irqLine >= CPU_USIU_IRQ_MIN_OFFSET)
- );
-}
-
-/*
- * Check if symbolic IRQ name is an UIMB IRQ
- */
-static inline int is_uimb_irq(const rtems_irq_number irqLine)
-{
- return (((int) irqLine <= CPU_UIMB_IRQ_MAX_OFFSET) &&
- ((int) irqLine >= CPU_UIMB_IRQ_MIN_OFFSET)
- );
-}
-
-/*
- * Check if symbolic IRQ name is a Processor IRQ
- */
-static inline int is_proc_irq(const rtems_irq_number irqLine)
-{
- return (((int) irqLine <= CPU_PROC_IRQ_MAX_OFFSET) &&
- ((int) irqLine >= CPU_PROC_IRQ_MIN_OFFSET)
- );
-}
-
-
-/*
- * Masks used to mask off the interrupts. For exmaple, for ILVL2, the
- * mask is used to mask off interrupts ILVL2, IRQ3, ILVL3, ... IRQ7
- * and ILVL7.
- *
- */
-const static unsigned int USIU_IvectMask[CPU_USIU_IRQ_COUNT] =
-{
- 0, /* external IRQ 0 */
- 0xFFFFFFFF << 31, /* internal level 0 */
- 0xFFFFFFFF << 30, /* external IRQ 1 */
- 0xFFFFFFFF << 29, /* internal level 1 */
- 0xFFFFFFFF << 28, /* external IRQ 2 */
- 0xFFFFFFFF << 27, /* internal level 2 */
- 0xFFFFFFFF << 26, /* external IRQ 3 */
- 0xFFFFFFFF << 25, /* internal level 3 */
- 0xFFFFFFFF << 24, /* external IRQ 4 */
- 0xFFFFFFFF << 23, /* internal level 4 */
- 0xFFFFFFFF << 22, /* external IRQ 5 */
- 0xFFFFFFFF << 21, /* internal level 5 */
- 0xFFFFFFFF << 20, /* external IRQ 6 */
- 0xFFFFFFFF << 19, /* internal level 6 */
- 0xFFFFFFFF << 18, /* external IRQ 7 */
- 0xFFFFFFFF << 17 /* internal level 7 */
-};
-
-
-/*
- * ------------------------ RTEMS Irq helper functions ----------------
- */
-
-/*
- * Caution : this function assumes the variable "internal_config"
- * is already set and that the tables it contains are still valid
- * and accessible.
- */
-static void compute_USIU_IvectMask_from_prio (void)
-{
- /*
- * In theory this is feasible. No time to code it yet. See i386/shared/irq.c
- * for an example based on 8259 controller mask. The actual masks defined
- * correspond to the priorities defined for the USIU in irq_init.c.
- */
-}
-
-/*
- * This function check that the value given for the irq line
- * is valid.
- */
-static int isValidInterrupt(int irq)
-{
- if ( (irq < CPU_MIN_OFFSET) || (irq > CPU_MAX_OFFSET)
- || (irq == CPU_UIMB_INTERRUPT) )
- return 0;
- return 1;
-}
-
-static int CPU_irq_enable_at_uimb(const rtems_irq_number irqLine)
-{
- if (!is_uimb_irq(irqLine))
- return 1;
- return 0;
-}
-
-static int CPU_irq_disable_at_uimb(const rtems_irq_number irqLine)
-{
- if (!is_uimb_irq(irqLine))
- return 1;
- return 0;
-}
-
-static int CPU_irq_enable_at_usiu(const rtems_irq_number irqLine)
-{
- int usiu_irq_index;
-
- if (!is_usiu_irq(irqLine))
- return 1;
-
- usiu_irq_index = ((int) (irqLine) - CPU_USIU_IRQ_MIN_OFFSET);
- ppc_cached_irq_mask |= (1 << (31-usiu_irq_index));
- usiu.simask = ppc_cached_irq_mask;
-
- return 0;
-}
-
-static int CPU_irq_disable_at_usiu(const rtems_irq_number irqLine)
-{
- int usiu_irq_index;
-
- if (!is_usiu_irq(irqLine))
- return 1;
-
- usiu_irq_index = ((int) (irqLine) - CPU_USIU_IRQ_MIN_OFFSET);
- ppc_cached_irq_mask &= ~(1 << (31-usiu_irq_index));
- usiu.simask = ppc_cached_irq_mask;
-
- return 0;
-}
-
-/*
- * --------------- RTEMS Single Irq Handler Mngt Routines ----------------
- */
-
-int CPU_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
-{
- rtems_interrupt_level level;
-
- if (!isValidInterrupt(irq->name)) {
- return 0;
- }
- /*
- * Check if default handler is actually connected. If not issue an error.
- * You must first get the current handler via CPU_get_current_idt_entry
- * and then disconnect it using CPU_delete_idt_entry.
- * RATIONALE : to always have the same transition by forcing the user
- * to get the previous handler before accepting to disconnect.
- */
- if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
- return 0;
- }
-
- rtems_interrupt_disable(level);
-
- /*
- * store the data provided by user
- */
- rtems_hdl_tbl[irq->name] = *irq;
-
- if (is_uimb_irq(irq->name)) {
- /*
- * Enable interrupt at UIMB level
- */
- CPU_irq_enable_at_uimb (irq->name);
- }
-
- if (is_usiu_irq(irq->name)) {
- /*
- * Enable interrupt at USIU level
- */
- CPU_irq_enable_at_usiu (irq->name);
- }
-
- if (is_proc_irq(irq->name)) {
- /*
- * Should Enable exception at processor level but not needed. Will restore
- * EE flags at the end of the routine anyway.
- */
- }
- /*
- * Enable interrupt on device
- */
- if (irq->on)
- irq->on(irq);
-
- rtems_interrupt_enable(level);
-
- return 1;
-}
-
-
-int CPU_get_current_rtems_irq_handler (rtems_irq_connect_data* irq)
-{
- if (!isValidInterrupt(irq->name)) {
- return 0;
- }
- *irq = rtems_hdl_tbl[irq->name];
- return 1;
-}
-
-int CPU_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
-{
- rtems_interrupt_level level;
-
- if (!isValidInterrupt(irq->name)) {
- return 0;
- }
- /*
- * Check if default handler is actually connected. If not issue an error.
- * You must first get the current handler via CPU_get_current_idt_entry
- * and then disconnect it using CPU_delete_idt_entry.
- * RATIONALE : to always have the same transition by forcing the user
- * to get the previous handler before accepting to disconnect.
- */
- if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
- return 0;
- }
- rtems_interrupt_disable(level);
-
- /*
- * Disable interrupt on device
- */
- if (irq->off)
- irq->off(irq);
-
- if (is_uimb_irq(irq->name)) {
- /*
- * disable interrupt at UIMB level
- */
- CPU_irq_disable_at_uimb (irq->name);
- }
- if (is_usiu_irq(irq->name)) {
- /*
- * disable interrupt at USIU level
- */
- CPU_irq_disable_at_usiu (irq->name);
- }
- if (is_proc_irq(irq->name)) {
- /*
- * disable exception at processor level
- */
- }
-
- /*
- * restore the default irq value
- */
- rtems_hdl_tbl[irq->name] = default_rtems_entry;
-
- rtems_interrupt_enable(level);
-
- return 1;
-}
-
-/*
- * ---------------- RTEMS Global Irq Handler Mngt Routines ----------------
- */
-
-int CPU_rtems_irq_mngt_set (rtems_irq_global_settings* config)
-{
- int i;
- rtems_interrupt_level level;
-
- /*
- * Store various code accelerators
- */
- internal_config = config;
- default_rtems_entry = config->defaultEntry;
- rtems_hdl_tbl = config->irqHdlTbl;
-
- rtems_interrupt_disable(level);
-
- /*
- * Start with UIMB IRQ
- */
- for (i = CPU_UIMB_IRQ_MIN_OFFSET; i <= CPU_UIMB_IRQ_MAX_OFFSET ; i++) {
- if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
- CPU_irq_enable_at_uimb (i);
- if (rtems_hdl_tbl[i].on)
- rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
- }
- else {
- if (rtems_hdl_tbl[i].off)
- rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
- CPU_irq_disable_at_uimb (i);
- }
- }
-
- /*
- * Continue with USIU IRQ
- * Set up internal tables used by rtems interrupt prologue
- */
- compute_USIU_IvectMask_from_prio ();
-
- for (i = CPU_USIU_IRQ_MIN_OFFSET; i <= CPU_USIU_IRQ_MAX_OFFSET ; i++) {
- if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
- CPU_irq_enable_at_usiu (i);
- if (rtems_hdl_tbl[i].on)
- rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
- }
- else {
- if (rtems_hdl_tbl[i].off)
- rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
- CPU_irq_disable_at_usiu (i);
- }
- }
-
- /*
- * Enable all UIMB interrupt lines, then enable at USIU.
- */
- imb.uimb.umcr |= UIMB_UMCR_IRQMUX(3);
- CPU_irq_enable_at_usiu (CPU_UIMB_INTERRUPT);
-
- /*
- * finish with Processor exceptions handled like IRQ
- */
- for (i = CPU_PROC_IRQ_MIN_OFFSET; i <= CPU_PROC_IRQ_MAX_OFFSET; i++) {
- if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
- if (rtems_hdl_tbl[i].on)
- rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
- }
- else {
- if (rtems_hdl_tbl[i].off)
- rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
- }
- }
- rtems_interrupt_enable(level);
- return 1;
-}
-
-int CPU_rtems_irq_mngt_get(rtems_irq_global_settings** config)
-{
- *config = internal_config;
- return 0;
-}
-
-
-/*
- * High level IRQ handler called from shared_raw_irq_code_entry
- */
-void C_dispatch_irq_handler (MPC5XX_Interrupt_frame *frame, unsigned int excNum)
-{
- register unsigned int irq;
- register unsigned uimbIntr; /* boolean */
- register unsigned oldMask; /* old siu pic masks */
- register unsigned msr;
- register unsigned new_msr;
-
- /*
- * Handle decrementer interrupt
- */
- if (excNum == ASM_DEC_VECTOR) {
- _CPU_MSR_GET(msr);
- new_msr = msr | MSR_EE;
- _CPU_MSR_SET(new_msr);
-
- rtems_hdl_tbl[CPU_DECREMENTER].hdl(rtems_hdl_tbl[CPU_DECREMENTER].handle);
-
- _CPU_MSR_SET(msr);
- return;
- }
-
- /*
- * Handle external interrupt generated by USIU on PPC core
- */
- while ((ppc_cached_irq_mask & usiu.sipend) != 0) {
- irq = (usiu.sivec >> 26);
- uimbIntr = (irq == CPU_UIMB_INTERRUPT);
- /*
- * Disable the interrupt of the same and lower priority.
- */
- oldMask = ppc_cached_irq_mask;
- ppc_cached_irq_mask = oldMask & USIU_IvectMask[irq];
- usiu.simask = ppc_cached_irq_mask;
- /*
- * Acknowledge current interrupt. This has no effect on internal level
- * interrupts.
- */
- usiu.sipend = (1 << (31 - irq));
-
- if (uimbIntr) {
- /*
- * Look at the bits set in the UIMB interrupt-pending register. The
- * highest-order set bit indicates the handler we will run.
- *
- * Unfortunately, we can't easily mask individual UIMB interrupts
- * unless they use USIU levels 0 to 6, so we must mask all low-level
- * (level > 7) UIMB interrupts while we service any interrupt.
- */
- int uipend = imb.uimb.uipend << 8;
-
- if (uipend == 0) { /* spurious interrupt? use last vector */
- irq = CPU_UIMB_IRQ_MAX_OFFSET;
- }
- else {
- irq = CPU_UIMB_IRQ_MIN_OFFSET;
- for ( ; (uipend & 0x8000000) == 0; uipend <<= 1) {
- irq++;
- }
- }
- }
- _CPU_MSR_GET(msr);
- new_msr = msr | MSR_EE;
- _CPU_MSR_SET(new_msr);
-
- rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
-
- _CPU_MSR_SET(msr);
-
- ppc_cached_irq_mask = oldMask;
- usiu.simask = ppc_cached_irq_mask;
- }
-}