summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/powerpc/mpc5xx/ictrl/ictrl.c
blob: 9590e5ba1a3a7970aea6738eee70b6c0628cf1c8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
 * mpc505/509 external interrupt controller management.
 */

#include "ictrl.h"

#include <rtems.h>
#include <rtems/score/ppc.h>

/*
 * Internal routines.
 */

static unsigned long volatile *const IRQAND     =
              (unsigned long volatile *const)0x8007EFA4;

static void nullHandler()
{
}

/* Interrupt dispatch table. */
static ExtIsrHandler extIrqHandlers[NUM_IRQS] =
{
  nullHandler,
  nullHandler,
  nullHandler,
  nullHandler,
  nullHandler,
  nullHandler,
  nullHandler
};


/* RTEMS external interrupt handler. Calls installed external interrupt
   handlers for every pending external interrupt in turn. */
static rtems_isr extIsr_( rtems_vector_number i )
{
#define BIT_NUMBER(val, bit) \
    asm volatile ( "cntlzw %0, %1; srawi %0, %0, 1": "=r" (bit) : "r" (val) );

  int bit;
  (void)i;

  BIT_NUMBER(*IRQAND & IMASK_ALL, bit);
  while ( bit < NUM_IRQS ) {
    extIrqHandlers[bit]();
    BIT_NUMBER(*IRQAND & IMASK_ALL, bit);
  }
}

/*
 * Public routines
 */

void extIrqSetHandler(ExtInt interrupt,ExtIsrHandler handler)
{
  extIrqHandlers[interrupt] = handler;
}

void extIsrInit( void )
{
  int i = 0;

  extIrqDisable(IMASK_ALL);
  for( i = 0; i < NUM_IRQS; i++)
    extIrqHandlers[i] = nullHandler;
  set_vector(extIsr_,PPC_IRQ_EXTERNAL,1);
}