summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/bfin/bf52x/interrupt/interrupt.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libcpu/bfin/bf52x/interrupt/interrupt.c')
-rw-r--r--c/src/lib/libcpu/bfin/bf52x/interrupt/interrupt.c642
1 files changed, 0 insertions, 642 deletions
diff --git a/c/src/lib/libcpu/bfin/bf52x/interrupt/interrupt.c b/c/src/lib/libcpu/bfin/bf52x/interrupt/interrupt.c
deleted file mode 100644
index 1b69046453..0000000000
--- a/c/src/lib/libcpu/bfin/bf52x/interrupt/interrupt.c
+++ /dev/null
@@ -1,642 +0,0 @@
-/**
- *@file interrupt.c
- *
- *@brief
- * - This file implements interrupt dispatcher. Most of the code is taken from
- * the 533 implementation for blackfin. Since 52X supports 56 line and 2 ISR
- * registers some portion is written twice.
- *
- * Target: TLL6527v1-0
- * Compiler:
- *
- * COPYRIGHT (c) 2010 by ECE Northeastern University.
- *
- * 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
- *
- * @author Rohan Kangralkar, ECE, Northeastern University
- * (kangralkar.r@husky.neu.edu)
- *
- * LastChange:
- */
-
-#include <rtems.h>
-#include <rtems/libio.h>
-
-#include <bsp.h>
-#include <libcpu/cecRegs.h>
-#include <libcpu/sicRegs.h>
-#include <string.h>
-#include <bsp/interrupt.h>
-
-#define SIC_IAR_COUNT_SET0 4
-#define SIC_IAR_BASE_ADDRESS_0 0xFFC00150
-
-/**
- * There are two implementations for the interrupt handler.
- * 1. INTERRUPT_USE_TABLE: uses tables for finding the right ISR.
- * 2. Uses link list to find the user ISR.
- *
- *
- * 1. INTERRUPT_USE_TABLE
- * Space requirement:
- * - Array to hold CEC masks size: CEC_INTERRUPT_COUNT(9)*(2*int).9*2*4= 72B
- * - Array to hold isr function pointers IRQ_MAX(56)*sizeof(bfin_isr_t)= 896B
- * - Array for bit twidlling 32 bytes.
- * - Global Mask 8 bytes.
- * - Total = 1008 Bytes Aprox
- *
- * Time requirements
- * The worst case time is about the same for jumping to the user ISR. With a
- * variance of one conditional statement.
- *
- * 2. Using link list.
- * Space requirement:
- * - Array to hold CEC mask CEC_INTERRUPT_COUNT(9)*(sizeof(vectors)).
- * 9*3*4= 108B
- * - Array to hold isr IRQ_MAX(56)*sizeof(bfin_isr_t) The structure has
- * additional pointers 56*7*4=1568B
- * - Global Mask 8 bytes.
- * Total = 1684.
- * Time requirements
- * In the worst case all the lines can be on one CEC line to 56 entries have
- * to be traversed to find the right user ISR.
- * But this implementation has benefit of being flexible, Providing
- * additional user assigned priority. and may consume less space
- * if all devices are not supported.
- */
-
-/**
- * TODO: To place the dispatcher routine code in L1.
- */
-
-#if INTERRUPT_USE_TABLE
-
-
-/******************************************************************************
- * Static variables
- *****************************************************************************/
-/**
- * @var sic_isr0_mask
- * @brief copy of the mask of SIC ISR. The SIC ISR is cleared by the device
- * the relevant SIC_ISRx bit is not cleared unless the interrupt
- * service routine clears the mechanism that generated interrupt
- */
-static uint32_t sic_isr0_mask = 0;
-
-/**
- * @var sic_isr0_mask
- * @brief copy of the mask of SIC ISR. The SIC ISR is cleared by the device
- * the relevant SIC_ISRx bit is not cleared unless the interrupt
- * service routine clears the mechanism that generated interrupt
- */
-static uint32_t sic_isr1_mask = 0;
-
-
-/**
- * @var sic_isr
- * @brief An array of sic register mask for each of the 16 core interrupt lines
- */
-static struct {
- uint32_t mask0;
- uint32_t mask1;
-} vectors[CEC_INTERRUPT_COUNT];
-
-/**
- * @var ivt
- * @brief Contains a table of ISR and arguments. The ISR jumps directly to
- * these ISR.
- */
-static bfin_isr_t ivt[IRQ_MAX];
-
-/**
- * http://graphics.stanford.edu/~seander/bithacks.html for more details
- */
-static const char clz_table[32] =
-{
- 0, 31, 9, 30, 3, 8, 18, 29, 2, 5, 7, 14, 12, 17,
- 22, 28, 1, 10, 4, 19, 6, 15, 13, 23, 11, 20, 16,
- 24, 21, 25, 26, 27
-};
-
-/**
- * finds the first bit set from the left. look at
- * http://graphics.stanford.edu/~seander/bithacks.html for more details
- * @param n
- * @return
- */
-static unsigned long clz(unsigned long n)
-{
- unsigned long c = 0x7dcd629; /* magic constant... */
-
- n |= (n >> 1);
- n |= (n >> 2);
- n |= (n >> 4);
- n |= (n >> 8);
- n |= (n >> 16);
- if (n == 0) return 32;
- n = c + (c * n);
- return 31 - clz_table[n >> 27]; /* For little endian */
-}
-
-
-
-/**
- * Centralized Interrupt dispatcher routine. This routine dispatches interrupts
- * to the user ISR. The priority is according to the blackfin SIC.
- * The first level of priority is handled in the hardware at the core event
- * controller. The second level of interrupt is handled according to the line
- * number that goes in to the SIC.
- * * SIC_0 has higher priority than SIC 1.
- * * Inside the SIC the priority is assigned according to the line number.
- * Lower the line number higher the priority.
- *
- * In order to change the interrupt priority we may
- * 1. change the SIC IAR registers or
- * 2. Assign priority and extract it inside this function and call the ISR
- * according tot the priority.
- *
- * @param vector IVG number.
- * @return
- */
-static rtems_isr interruptHandler(rtems_vector_number vector) {
- uint32_t mask = 0;
- int id = 0;
- /**
- * Enable for debugging
- *
- * static volatile uint32_t spurious_sic0 = 0;
- * static volatile uint32_t spurious_source = 0;
- * static volatile uint32_t spurious_sic1 = 0;
- */
-
- /**
- * Extract the vector number relative to the SIC start line
- */
- vector -= CEC_INTERRUPT_BASE_VECTOR;
-
- /**
- * Check for bounds
- */
- if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) {
-
- /**
- * Extract information and execute ISR from SIC 0
- */
- mask = *(uint32_t volatile *) SIC_ISR &
- *(uint32_t volatile *) SIC_IMASK & vectors[vector].mask0;
- id = clz(mask);
- if ( SIC_ISR0_MAX > id ) {
- /** Parameter check */
- if( NULL != ivt[id].pFunc) {
- /** Call the relevant function with argument */
- ivt[id].pFunc( ivt[id].pArg );
- } else {
- /**
- * spurious interrupt we should not be getting this
- * spurious_sic0++;
- * spurious_source = id;
- */
- }
- } else {
- /**
- * we look at SIC 1
- */
- }
-
-
- /**
- * Extract information and execute ISR from SIC 1
- */
- mask = *(uint32_t volatile *) (SIC_ISR + SIC_ISR_PITCH) &
- *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) &
- vectors[vector].mask1;
- id = clz(mask)+SIC_ISR0_MAX;
- if ( IRQ_MAX > id ) {
- /** Parameter Check */
- if( NULL != ivt[id].pFunc ) {
- /** Call the relevant function with argument */
- ivt[id].pFunc( ivt[id].pArg );
- } else {
- /**
- * spurious interrupt we should not be getting this
- *
- * spurious_sic1++;
- * spurious_source = id;
- */
- }
- } else {
- /**
- * we continue
- */
- }
-
- }
-}
-
-
-
-/**
- * This routine registers a new ISR. It will write a new entry to the IVT table
- * @param isr contains a callback function and source
- * @return rtems status code
- */
-rtems_status_code bfin_interrupt_register(bfin_isr_t *isr) {
- rtems_interrupt_level isrLevel;
- int id = 0;
- int position = 0;
-
- /**
- * Sanity Check
- */
- if ( NULL == isr ){
- return RTEMS_UNSATISFIED;
- }
-
- /**
- * Sanity check. The register function should at least provide callback func
- */
- if ( NULL == isr->pFunc ) {
- return RTEMS_UNSATISFIED;
- }
-
- id = isr->source;
-
- /**
- * Parameter Check. We already have a function registered here. First
- * unregister and then a new function can be allocated.
- */
- if ( NULL != ivt[id].pFunc ) {
- return RTEMS_UNSATISFIED;
- }
-
- rtems_interrupt_disable(isrLevel);
- /**
- * Assign the new function pointer to the ISR Dispatcher
- * */
- ivt[id].pFunc = isr->pFunc;
- ivt[id].pArg = isr->pArg;
-
-
- /** find out which isr mask has to be set to enable the interrupt */
- if ( SIC_ISR0_MAX > id ) {
- sic_isr0_mask |= 0x1<<id;
- *(uint32_t volatile *) SIC_IMASK |= 0x1<<id;
- } else {
- position = id - SIC_ISR0_MAX;
- sic_isr1_mask |= 0x1<<position;
- *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) |= 0x1<<position;
- }
-
- rtems_interrupt_enable(isrLevel);
-
- return RTEMS_SUCCESSFUL;
-}
-
-
-/**
- * This function unregisters a registered interrupt handler.
- * @param isr
- */
-rtems_status_code bfin_interrupt_unregister(bfin_isr_t *isr) {
- rtems_interrupt_level isrLevel;
- int id = 0;
- int position = 0;
-
- /**
- * Sanity Check
- */
- if ( NULL == isr ){
- return RTEMS_UNSATISFIED;
- }
-
- id = isr->source;
-
- rtems_interrupt_disable(isrLevel);
- /**
- * Assign the new function pointer to the ISR Dispatcher
- * */
- ivt[id].pFunc = NULL;
- ivt[id].pArg = NULL;
-
-
- /** find out which isr mask has to be set to enable the interrupt */
- if ( SIC_ISR0_MAX > id ) {
- sic_isr0_mask &= ~(0x1<<id);
- *(uint32_t volatile *) SIC_IMASK &= ~(0x1<<id);
- } else {
- position = id - SIC_ISR0_MAX;
- sic_isr1_mask &= ~(0x1<<position);
- *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) &= ~(0x1<<position);
- }
-
- rtems_interrupt_enable(isrLevel);
-
- return RTEMS_SUCCESSFUL;
-}
-
-
-
-
-/**
- * blackfin interrupt initialization routine. It initializes the bfin ISR
- * dispatcher. It will also create SIC CEC map which will be used for
- * identifying the ISR.
- */
-void bfin_interrupt_init(void) {
- int source;
- int vector;
- uint32_t r;
- int i;
- int j;
-
- *(uint32_t volatile *) SIC_IMASK = 0;
- *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) = 0;
-
- memset(vectors, 0, sizeof(vectors));
- /* build mask0 showing what SIC sources drive each CEC vector */
- source = 0;
-
- /**
- * The bf52x has 8 IAR registers but they do not have a constant pitch.
- *
- */
- for (i = 0; i < SIC_IAR_COUNT; i++) {
- if ( SIC_IAR_COUNT_SET0 > i ) {
- r = *(uint32_t volatile *) (SIC_IAR_BASE_ADDRESS + i * SIC_IAR_PITCH);
- } else {
- r = *(uint32_t volatile *) (SIC_IAR_BASE_ADDRESS_0 +
- ((i-SIC_IAR_COUNT_SET0) * SIC_IAR_PITCH));
- }
-
- for (j = 0; j < 8; j++) {
- vector = r & 0x0f;
- if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) {
- /* install our local handler */
- if (vectors[vector].mask0 == 0 && vectors[vector].mask1 == 0){
- set_vector(interruptHandler, vector + CEC_INTERRUPT_BASE_VECTOR, 1);
- }
- if ( SIC_ISR0_MAX > source ) {
- vectors[vector].mask0 |= (1 << source);
- } else {
- vectors[vector].mask1 |= (1 << (source - SIC_ISR0_MAX));
- }
- }
- r >>= 4;
- source++;
- }
- }
-}
-
-
-
-
-
-#else
-
-static struct {
- uint32_t mask0;
- uint32_t mask1;
- bfin_isr_t *head;
-} vectors[CEC_INTERRUPT_COUNT];
-
-static uint32_t globalMask0;
-static uint32_t globalMask1;
-
-static rtems_isr interruptHandler(rtems_vector_number vector) {
- bfin_isr_t *isr = NULL;
- uint32_t sourceMask0 = 0;
- uint32_t sourceMask1 = 0;
- rtems_interrupt_level isrLevel;
-
- rtems_interrupt_disable(isrLevel);
- vector -= CEC_INTERRUPT_BASE_VECTOR;
- if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) {
- isr = vectors[vector].head;
- sourceMask0 = *(uint32_t volatile *) SIC_ISR &
- *(uint32_t volatile *) SIC_IMASK;
- sourceMask1 = *(uint32_t volatile *) (SIC_ISR + SIC_ISR_PITCH) &
- *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH);
- while (isr) {
- if ((sourceMask0 & isr->mask0) || (sourceMask1 & isr->mask1)) {
- isr->isr(isr->_arg);
- sourceMask0 = *(uint32_t volatile *) SIC_ISR &
- *(uint32_t volatile *) SIC_IMASK;
- sourceMask1 = *(uint32_t volatile *) (SIC_ISR + SIC_ISR_PITCH) &
- *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH);
- }
- isr = isr->next;
- }
- }
- rtems_interrupt_enable(isrLevel);
-}
-
-/**
- * Initializes the interrupt module
- */
-void bfin_interrupt_init(void) {
- int source;
- int vector;
- uint32_t r;
- int i;
- int j;
-
- globalMask0 = ~(uint32_t) 0;
- globalMask1 = ~(uint32_t) 0;
- *(uint32_t volatile *) SIC_IMASK = 0;
- *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) = 0;
-
- memset(vectors, 0, sizeof(vectors));
- /* build mask0 showing what SIC sources drive each CEC vector */
- source = 0;
-
- /**
- * The bf52x has 8 IAR registers but they do not have a constant pitch.
- *
- */
- for (i = 0; i < SIC_IAR_COUNT; i++) {
- if ( SIC_IAR_COUNT_SET0 > i ) {
- r = *(uint32_t volatile *) (SIC_IAR_BASE_ADDRESS + i * SIC_IAR_PITCH);
- } else {
- r = *(uint32_t volatile *) (SIC_IAR_BASE_ADDRESS_0 +
- ((i-SIC_IAR_COUNT_SET0) * SIC_IAR_PITCH));
- }
- for (j = 0; j < 8; j++) {
- vector = r & 0x0f;
- if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) {
- /* install our local handler */
- if (vectors[vector].mask0 == 0 && vectors[vector].mask1 == 0){
- set_vector(interruptHandler, vector + CEC_INTERRUPT_BASE_VECTOR, 1);
- }
- if ( SIC_ISR0_MAX > source ) {
- vectors[vector].mask0 |= (1 << source);
- } else {
- vectors[vector].mask1 |= (1 << (source - SIC_ISR0_MAX));
- }
- }
- r >>= 4;
- source++;
- }
- }
-}
-
-/* modify SIC_IMASK based on ISR list for a particular CEC vector */
-static void setMask(uint32_t vector) {
- bfin_isr_t *isr = NULL;
- uint32_t mask = 0;
- uint32_t r = 0;
-
- mask = 0;
- isr = vectors[vector].head;
- while (isr) {
- mask |= isr->mask0;
- isr = isr->next;
- }
- r = *(uint32_t volatile *) SIC_IMASK;
- r &= ~vectors[vector].mask0;
- r |= mask;
- r &= globalMask0;
- *(uint32_t volatile *) SIC_IMASK = r;
-
-
- mask = 0;
- isr = vectors[vector].head;
- while (isr) {
- mask |= isr->mask1;
- isr = isr->next;
- }
- r = *(uint32_t volatile *) (SIC_IMASK+ SIC_IMASK_PITCH);
- r &= ~vectors[vector].mask1;
- r |= mask;
- r &= globalMask1;
- *(uint32_t volatile *) (SIC_IMASK+ SIC_IMASK_PITCH) = r;
-}
-
-/* add an ISR to the list for whichever vector it belongs to */
-rtems_status_code bfin_interrupt_register(bfin_isr_t *isr) {
- bfin_isr_t *walk;
- rtems_interrupt_level isrLevel;
-
- /* find the appropriate vector */
- for (isr->vector = 0; isr->vector < CEC_INTERRUPT_COUNT; isr->vector++)
- if ( (vectors[isr->vector].mask0 & (1 << isr->source) ) || \
- (vectors[isr->vector].mask1 & (1 << (isr->source - SIC_ISR0_MAX)) ))
- break;
- if (isr->vector < CEC_INTERRUPT_COUNT) {
- isr->next = NULL;
- isr->mask0 = 0;
- isr->mask1 = 0;
- rtems_interrupt_disable(isrLevel);
- /* find the current end of the list */
- walk = vectors[isr->vector].head;
- while (walk && walk->next)
- walk = walk->next;
- /* append new isr to list */
- if (walk)
- walk->next = isr;
- else
- vectors[isr->vector].head = isr;
- rtems_interrupt_enable(isrLevel);
- } else
- /* we failed, but make vector a legal value so other calls into
- this module with this isr descriptor won't do anything bad */
- isr->vector = 0;
- return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code bfin_interrupt_unregister(bfin_isr_t *isr) {
- bfin_isr_t *walk, *prev;
- rtems_interrupt_level isrLevel;
-
- rtems_interrupt_disable(isrLevel);
- walk = vectors[isr->vector].head;
- prev = NULL;
- /* find this isr in our list */
- while (walk && walk != isr) {
- prev = walk;
- walk = walk->next;
- }
- if (walk) {
- /* if found, remove it */
- if (prev)
- prev->next = walk->next;
- else
- vectors[isr->vector].head = walk->next;
- /* fix up SIC_IMASK if necessary */
- setMask(isr->vector);
- }
- rtems_interrupt_enable(isrLevel);
- return RTEMS_SUCCESSFUL;
-}
-
-void bfin_interrupt_enable(bfin_isr_t *isr, bool enable) {
- rtems_interrupt_level isrLevel;
-
- rtems_interrupt_disable(isrLevel);
- if ( SIC_ISR0_MAX > isr->source ) {
- isr->mask0 = enable ? (1 << isr->source) : 0;
- *(uint32_t volatile *) SIC_IMASK |= isr->mask0;
- } else {
- isr->mask1 = enable ? (1 << (isr->source - SIC_ISR0_MAX)) : 0;
- *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) |= isr->mask1;
- }
-
- //setMask(isr->vector);
- rtems_interrupt_enable(isrLevel);
-}
-
-void bfin_interrupt_enable_all(int source, bool enable) {
- rtems_interrupt_level isrLevel;
- int vector;
- bfin_isr_t *walk;
-
- for (vector = 0; vector < CEC_INTERRUPT_COUNT; vector++)
- if ( (vectors[vector].mask0 & (1 << source) ) || \
- (vectors[vector].mask1 & (1 << (source - SIC_ISR0_MAX)) ))
- break;
- if (vector < CEC_INTERRUPT_COUNT) {
- rtems_interrupt_disable(isrLevel);
- walk = vectors[vector].head;
- while (walk) {
- walk->mask0 = enable ? (1 << source) : 0;
- walk = walk->next;
- }
-
- walk = vectors[vector].head;
- while (walk) {
- walk->mask1 = enable ? (1 << (source - SIC_ISR0_MAX)) : 0;
- walk = walk->next;
- }
- setMask(vector);
- rtems_interrupt_enable(isrLevel);
- }
-}
-
-void bfin_interrupt_enable_global(int source, bool enable) {
- int vector;
- rtems_interrupt_level isrLevel;
-
- for (vector = 0; vector < CEC_INTERRUPT_COUNT; vector++)
- if ( (vectors[vector].mask0 & (1 << source) ) || \
- (vectors[vector].mask1 & (1 << (source - SIC_ISR0_MAX)) ))
- break;
- if (vector < CEC_INTERRUPT_COUNT) {
- rtems_interrupt_disable(isrLevel);
- if ( SIC_ISR0_MAX > source ) {
- if (enable)
- globalMask0 |= 1 << source;
- else
- globalMask0 &= ~(1 << source);
- }else {
- if (enable)
- globalMask1 |= 1 << (source - SIC_ISR0_MAX);
- else
- globalMask1 &= ~(1 << (source - SIC_ISR0_MAX));
- }
- setMask(vector);
- rtems_interrupt_enable(isrLevel);
- }
-}
-
-#endif