Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:40

0001 /*  Support for Blackfin interrupt controller
0002  *
0003  *  Copyright (c) 2008 Kallisti Labs, Los Gatos, CA, USA
0004  *             written by Allan Hessenflow <allanh@kallisti.com>
0005  *
0006  *  The license and distribution terms for this file may be
0007  *  found in the file LICENSE in this distribution or at
0008  *  http://www.rtems.org/license/LICENSE.
0009  */
0010 
0011 
0012 #include <rtems.h>
0013 #include <rtems/libio.h>
0014 
0015 #include <bsp.h>
0016 #include <libcpu/cecRegs.h>
0017 #include <libcpu/sicRegs.h>
0018 #include <string.h>
0019 #include <libcpu/interrupt.h>
0020 
0021 
0022 static struct {
0023   uint32_t mask;
0024   bfin_isr_t *head;
0025 } vectors[CEC_INTERRUPT_COUNT];
0026 
0027 static uint32_t globalMask;
0028 
0029 
0030 static rtems_isr interruptHandler(rtems_vector_number vector) {
0031   bfin_isr_t *isr;
0032   uint32_t sourceMask;
0033 
0034   vector -= CEC_INTERRUPT_BASE_VECTOR;
0035   if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) {
0036     isr = vectors[vector].head;
0037     sourceMask = *(uint32_t volatile *) SIC_ISR &
0038                  *(uint32_t volatile *) SIC_IMASK;
0039     while (isr) {
0040       if (sourceMask & isr->mask) {
0041         isr->isr(isr->source);
0042         sourceMask = *(uint32_t volatile *) SIC_ISR &
0043                      *(uint32_t volatile *) SIC_IMASK;
0044       }
0045       isr = isr->next;
0046     }
0047   }
0048 }
0049 
0050 void bfin_interrupt_init(void) {
0051   int source;
0052   int vector;
0053   uint32_t r;
0054   int i;
0055   int j;
0056 
0057   globalMask = ~(uint32_t) 0;
0058   *(uint32_t volatile *) SIC_IMASK = 0;
0059   memset(vectors, 0, sizeof(vectors));
0060   /* build mask showing what SIC sources drive each CEC vector */
0061   source = 0;
0062   for (i = 0; i < SIC_IAR_COUNT; i++) {
0063     r = *(uint32_t volatile *) (SIC_IAR_BASE_ADDRESS + i * SIC_IAR_PITCH);
0064     for (j = 0; j < 8; j++) {
0065       vector = r & 0x0f;
0066       if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) {
0067         if (vectors[vector].mask == 0)
0068           /* install our local handler */
0069           set_vector(interruptHandler, vector + CEC_INTERRUPT_BASE_VECTOR, 1);
0070         vectors[vector].mask |= (1 << source);
0071       }
0072       r >>= 4;
0073       source++;
0074     }
0075   }
0076 }
0077 
0078 /* modify SIC_IMASK based on ISR list for a particular CEC vector */
0079 static void setMask(int vector) {
0080   bfin_isr_t *isr;
0081   uint32_t mask;
0082   uint32_t r;
0083 
0084   mask = 0;
0085   isr = vectors[vector].head;
0086   while (isr) {
0087     mask |= isr->mask;
0088     isr = isr->next;
0089   }
0090   r = *(uint32_t volatile *) SIC_IMASK;
0091   r &= ~vectors[vector].mask;
0092   r |= mask;
0093   r &= globalMask;
0094   *(uint32_t volatile *) SIC_IMASK = r;
0095 }
0096 
0097 /* add an ISR to the list for whichever vector it belongs to */
0098 void bfin_interrupt_register(bfin_isr_t *isr) {
0099   bfin_isr_t *walk;
0100   rtems_interrupt_level isrLevel;
0101 
0102   /* find the appropriate vector */
0103   for (isr->vector = 0; isr->vector < CEC_INTERRUPT_COUNT; isr->vector++)
0104     if (vectors[isr->vector].mask & (1 << isr->source))
0105       break;
0106   if (isr->vector < CEC_INTERRUPT_COUNT) {
0107     isr->next = NULL;
0108     isr->mask = 0;
0109     rtems_interrupt_disable(isrLevel);
0110     /* find the current end of the list */
0111     walk = vectors[isr->vector].head;
0112     while (walk && walk->next)
0113       walk = walk->next;
0114     /* append new isr to list */
0115     if (walk)
0116       walk->next = isr;
0117     else
0118       vectors[isr->vector].head = isr;
0119     rtems_interrupt_enable(isrLevel);
0120   } else
0121     /* we failed, but make vector a legal value so other calls into
0122        this module with this isr descriptor won't do anything bad */
0123     isr->vector = 0;
0124 }
0125 
0126 void bfin_interrupt_unregister(bfin_isr_t *isr) {
0127   bfin_isr_t *walk, *prev;
0128   rtems_interrupt_level isrLevel;
0129 
0130   rtems_interrupt_disable(isrLevel);
0131   walk = vectors[isr->vector].head;
0132   prev = NULL;
0133   /* find this isr in our list */
0134   while (walk && walk != isr) {
0135     prev = walk;
0136     walk = walk->next;
0137   }
0138   if (walk) {
0139     /* if found, remove it */
0140     if (prev)
0141       prev->next = walk->next;
0142     else
0143       vectors[isr->vector].head = walk->next;
0144     /* fix up SIC_IMASK if necessary */
0145     setMask(isr->vector);
0146   }
0147   rtems_interrupt_enable(isrLevel);
0148 }
0149 
0150 void bfin_interrupt_enable(bfin_isr_t *isr, bool enable) {
0151   rtems_interrupt_level isrLevel;
0152 
0153   rtems_interrupt_disable(isrLevel);
0154   isr->mask = enable ? (1 << isr->source) : 0;
0155   setMask(isr->vector);
0156   rtems_interrupt_enable(isrLevel);
0157 }
0158 
0159 void bfin_interrupt_enable_all(int source, bool enable) {
0160   rtems_interrupt_level isrLevel;
0161   int vector;
0162   bfin_isr_t *walk;
0163 
0164   for (vector = 0; vector < CEC_INTERRUPT_COUNT; vector++)
0165     if (vectors[vector].mask & (1 << source))
0166       break;
0167   if (vector < CEC_INTERRUPT_COUNT) {
0168     rtems_interrupt_disable(isrLevel);
0169     walk = vectors[vector].head;
0170     while (walk) {
0171       walk->mask = enable ? (1 << source) : 0;
0172       walk = walk->next;
0173     }
0174     setMask(vector);
0175     rtems_interrupt_enable(isrLevel);
0176   }
0177 }
0178 
0179 void bfin_interrupt_enable_global(int source, bool enable) {
0180   int vector;
0181   rtems_interrupt_level isrLevel;
0182 
0183   for (vector = 0; vector < CEC_INTERRUPT_COUNT; vector++)
0184     if (vectors[vector].mask & (1 << source))
0185       break;
0186   if (vector < CEC_INTERRUPT_COUNT) {
0187     rtems_interrupt_disable(isrLevel);
0188     if (enable)
0189       globalMask |= 1 << source;
0190     else
0191       globalMask &= ~(1 << source);
0192     setMask(vector);
0193     rtems_interrupt_enable(isrLevel);
0194   }
0195 }
0196