source: rtems/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c @ 4f5d1c9f

4.104.115
Last change on this file since 4f5d1c9f was 4f5d1c9f, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on 03/27/10 at 15:00:43

removed warnings

  • Property mode set to 100644
File size: 31.3 KB
Line 
1/*===============================================================*\
2| Project: RTEMS generic MPC5200 BSP                              |
3+-----------------------------------------------------------------+
4| Partially based on the code references which are named below.   |
5| Adaptions, modifications, enhancements and any recent parts of  |
6| the code are:                                                   |
7|                    Copyright (c) 2005                           |
8|                    Embedded Brains GmbH                         |
9|                    Obere Lagerstr. 30                           |
10|                    D-82178 Puchheim                             |
11|                    Germany                                      |
12|                    rtems@embedded-brains.de                     |
13+-----------------------------------------------------------------+
14| The license and distribution terms for this file may be         |
15| found in the file LICENSE in this distribution or at            |
16|                                                                 |
17| http://www.rtems.com/license/LICENSE.                           |
18|                                                                 |
19+-----------------------------------------------------------------+
20| this file contains the irq controller handler                   |
21\*===============================================================*/
22/***********************************************************************/
23/*                                                                     */
24/*   Module:       irq.c                                               */
25/*   Date:         07/17/2003                                          */
26/*   Purpose:      RTEMS MPC5x00 CPU main interrupt handler & routines */
27/*                                                                     */
28/*---------------------------------------------------------------------*/
29/*                                                                     */
30/*   Description:  This file contains the implementation of the        */
31/*                 functions described in irq.h                        */
32/*                                                                     */
33/*---------------------------------------------------------------------*/
34/*                                                                     */
35/*   Code                                                              */
36/*   References:   MPC8260ads main interrupt handler & routines        */
37/*   Module:       irc.c                                               */
38/*   Project:      RTEMS 4.6.0pre1 / MCF8260ads BSP                    */
39/*   Version       1.2                                                 */
40/*   Date:         04/18/2002                                          */
41/*                                                                     */
42/*   Author(s) / Copyright(s):                                         */
43/*                                                                     */
44/*   Copyright (C) 1998, 1999 valette@crf.canon.fr                     */
45/*                                                                     */
46/*   Modified for mpc8260 Andy Dachs <a.dachs@sstl.co.uk>              */
47/*   Surrey Satellite Technology Limited, 2000                         */
48/*   Nested exception handlers not working yet.                        */
49/*                                                                     */
50/*   The license and distribution terms for this file may be           */
51/*   found in found in the file LICENSE in this distribution or at     */
52/*   http://www.rtems.com/license/LICENSE.                        */
53/*                                                                     */
54/*---------------------------------------------------------------------*/
55/*                                                                     */
56/*   Partially based on the code references which are named above.     */
57/*   Adaptions, modifications, enhancements and any recent parts of    */
58/*   the code are under the right of                                   */
59/*                                                                     */
60/*         IPR Engineering, Dachauer Straße 38, D-80335 MÃŒnchen        */
61/*                        Copyright(C) 2003                            */
62/*                                                                     */
63/*---------------------------------------------------------------------*/
64/*                                                                     */
65/*   IPR Engineering makes no representation or warranties with        */
66/*   respect to the performance of this computer program, and          */
67/*   specifically disclaims any responsibility for any damages,        */
68/*   special or consequential, connected with the use of this program. */
69/*                                                                     */
70/*---------------------------------------------------------------------*/
71/*                                                                     */
72/*   Version history:  1.0                                             */
73/*                                                                     */
74/***********************************************************************/
75
76#include <rtems.h>
77
78#include <libcpu/powerpc-utility.h>
79#include <bsp/vectors.h>
80
81#include <bsp.h>
82#include <bsp/irq.h>
83#include <bsp/irq-generic.h>
84#include <bsp/mpc5200.h>
85
86/*
87 * bit in the SIU mask registers (PPC bit numbering) that should
88 * be set to enable the relevant interrupt, mask of 32 is for unused entries
89 *
90 */
91const static unsigned int SIU_MaskBit [BSP_SIU_IRQ_NUMBER] = {
92  0, 1, 2, 3,                   /* smart_comm, psc1, psc2, psc3            */
93  4, 5, 6, 7,                   /* irda/psc6, eth, usb, ata                */
94  8, 9, 10, 11,                 /* pci_ctrl, pci_sc_rx, pci_sc_tx, psc4    */
95  12, 13, 14, 15,               /* psc5,spi_modf, spi_spif, i2c1           */
96  16, 17, 18, 19,               /* i2c, can1, can2, ir_rx                  */
97  20, 21, 15, 16,               /* ir_rx, xlb_arb, slice_tim2, irq1,       */
98  17, 18, 19, 20,               /* irq2, irq3, lo_int, rtc_pint            */
99  21, 22, 23, 24,               /* rtc_sint, gpio_std, gpio_wkup, tmr0     */
100  25, 26, 27, 28,               /* tmr1, tmr2, tmr3, tmr4                  */
101  29, 30, 31, 32,               /* tmr5, tmr6, tmr7, res                   */
102  32, 32, 32                    /* res, res, res                           */
103};
104
105static unsigned char irqPrioTable [BSP_SIU_IRQ_NUMBER] = {
106/* per. int. priorities (0-7) / 4bit coding / msb is HI/LO selection               */
107/* msb = 0 -> non-critical per. int. is routed to main int. (LO_int)               */
108/* msb = 1 -> critical per. int. is routed to critical int. (HI_int)               */
109  0xF, 0, 0, 0,                 /* smart_comm (do not change!), psc1, psc2, psc3             */
110  0, 0, 0, 0,                   /* irda, eth, usb, ata                                       */
111  0, 0, 0, 0,                   /* pci_ctrl, pci_sc_rx, pci_sc_tx, res                       */
112  0, 0, 0, 0,                   /* res, spi_modf, spi_spif, i2c1                             */
113  0, 0, 0, 0,                   /* i2c, can1, can2, ir_rx                                    */
114  0, 0,                         /* ir_rx, xlb_arb                                            */
115/* main interrupt priorities (0-7) / 4bit coding / msb is INT/SMI selection        */
116/* msb = 0 -> main int. is routed to processor INT (low vector base 0x500 )        */
117/* msb = 1 -> main int. is routed to processor SMI (low vector base 0x1400 )       */
118  0, 0,                         /* slice_tim2, irq1                                          */
119  0, 0, 0, 0,                   /* irq2, irq3, lo_int, rtc_pint                              */
120  0, 0, 0, 0,                   /* rtc_sint, gpio_std, gpio_wkup, tmr0                       */
121  0, 0, 0, 0,                   /* tmr1, tmr2, tmr3, tmr4                                    */
122  0, 0, 0,                      /* tmr5, tmr6, tmr7                                          */
123  /* critical interrupt priorities (0-3) / 2bit coding / no special purpose of msb */
124  0,                            /* irq0                                                      */
125  0, 0, 0                       /* slice_tim1, hi_int, ccs_wkup                              */
126};
127
128static uint32_t irqMaskTable [BSP_PER_IRQ_NUMBER + BSP_MAIN_IRQ_NUMBER];
129
130/*
131 * Check if symbolic IRQ name is a Processor IRQ
132 */
133static inline bool is_processor_irq( rtems_vector_number irqLine)
134{
135
136  return ((irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET)
137    && (irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET));
138}
139
140/*
141 * Check for SIU IRQ and return base index
142 */
143static inline bool is_siu_irq( rtems_vector_number irqLine)
144{
145
146  return ((irqLine <= BSP_SIU_IRQ_MAX_OFFSET)
147    && (irqLine >= BSP_SIU_IRQ_LOWEST_OFFSET));
148}
149
150/*
151 * Check for SIU IRQ and return base index
152 */
153static inline int get_siu_irq_base_index( rtems_vector_number irqLine)
154{
155  if (irqLine <= BSP_PER_IRQ_MAX_OFFSET)
156    return BSP_PER_IRQ_LOWEST_OFFSET;
157
158  if (irqLine <= BSP_MAIN_IRQ_MAX_OFFSET)
159    return BSP_MAIN_IRQ_LOWEST_OFFSET;
160
161  if (irqLine <= BSP_CRIT_IRQ_MAX_OFFSET)
162    return BSP_CRIT_IRQ_LOWEST_OFFSET;
163
164  return -1;
165}
166
167static inline void BSP_enable_per_irq_at_siu(
168  rtems_vector_number irqLine
169)
170{
171  uint8_t lo_hi_ind = 0,
172    prio_index_offset;
173  uint32_t *reg;
174  volatile uint32_t per_pri_1,
175    main_pri_1,
176    crit_pri_main_mask,
177    per_mask;
178
179  /* calculate the index offset of priority value bit field */
180  prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
181
182  /* set interrupt priorities */
183  if (irqPrioTable [irqLine] <= 15) {
184
185    /* set peripheral int priority */
186    reg = (uint32_t *) (&(mpc5200.per_pri_1));
187
188    /* choose proper register */
189    reg += (irqLine >> 3);
190
191    /* set priority as given in priority table */
192    *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2)));
193
194    /* test msb (hash-bit) and set LO_/HI_int indicator */
195    if ((lo_hi_ind = (irqPrioTable [irqLine] >> 3))) {
196
197      /* set critical HI_int priority */
198      reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
199      *reg |= (irqPrioTable [BSP_SIU_IRQ_HI_INT] << 26);
200
201      /*
202       * critical interrupt handling for the 603le core is not
203       * yet supported, routing of critical interrupts is forced
204       * to core_int (bit 31 / CEb)
205       */
206      mpc5200.ext_en_type |= 1;
207
208    } else {
209      if (irqPrioTable [irqLine] <= 15) {
210        /* set main LO_int priority */
211        reg = (uint32_t *) (&(mpc5200.main_pri_1));
212        *reg |= (irqPrioTable [BSP_SIU_IRQ_LO_INT] << 16);
213      }
214    }
215  }
216
217  /* if LO_int ind., enable (unmask) main interrupt */
218  if (!lo_hi_ind) {
219    mpc5200.crit_pri_main_mask &=
220      ~(0x80000000 >> SIU_MaskBit [BSP_SIU_IRQ_LO_INT]);
221  }
222
223  /* enable (unmask) peripheral interrupt */
224  mpc5200.per_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]);
225
226  main_pri_1 = mpc5200.main_pri_1;
227  crit_pri_main_mask = mpc5200.crit_pri_main_mask;
228  per_pri_1 = mpc5200.per_pri_1;
229  per_mask = mpc5200.per_mask;
230
231}
232
233static inline void BSP_enable_main_irq_at_siu(
234  rtems_vector_number irqLine
235)
236{
237
238  uint8_t prio_index_offset;
239  uint32_t *reg;
240
241  /* calculate the index offset of priority value bit field */
242  prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
243
244  /* set main interrupt priority */
245  if (irqPrioTable [irqLine] <= 15) {
246
247    /* set main int priority */
248    reg = (uint32_t *) (&(mpc5200.main_pri_1));
249
250    /* choose proper register */
251    reg += (irqLine >> 3);
252
253    /* set priority as given in priority table */
254    *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2)));
255
256    if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
257      /* enable external irq-pin */
258      mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
259    }
260  }
261
262  /* enable (unmask) main interrupt */
263  mpc5200.crit_pri_main_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]);
264
265}
266
267static inline void BSP_enable_crit_irq_at_siu(
268  rtems_vector_number irqLine
269)
270{
271  uint8_t prio_index_offset;
272  uint32_t *reg;
273
274  prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
275
276  /*
277   * critical interrupt handling for the 603Le core is not
278   * yet supported, routing of critical interrupts is forced
279   * to core_int (bit 31 / CEb)
280   */
281  mpc5200.ext_en_type |= 1;
282
283  /* set critical interrupt priorities */
284  if (irqPrioTable [irqLine] <= 3) {
285
286    /* choose proper register */
287    reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
288
289    /* set priority as given in priority table */
290    *reg |= (irqPrioTable [irqLine] << (30 - (prio_index_offset << 1)));
291
292    /* external irq0-pin */
293    if (irqLine == BSP_SIU_IRQ_IRQ1) {
294      /* enable external irq-pin */
295      mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
296    }
297  }
298}
299
300static inline void BSP_disable_per_irq_at_siu(
301  rtems_vector_number irqLine
302)
303{
304  uint8_t prio_index_offset;
305  uint32_t *reg;
306
307  /* calculate the index offset of priority value bit field */
308  prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
309
310  /* disable (mask) peripheral interrupt */
311  mpc5200.per_mask |= (0x80000000 >> SIU_MaskBit [irqLine]);
312
313  /* reset priority to lowest level (reset value) */
314  reg = (uint32_t *) (&(mpc5200.per_pri_1));
315  reg += (irqLine >> 3);
316  *reg &= ~(15 << (28 - (prio_index_offset << 2)));
317}
318
319static inline void BSP_disable_main_irq_at_siu(
320  rtems_vector_number irqLine
321)
322{
323  uint8_t prio_index_offset;
324  uint32_t *reg;
325
326  /* calculate the index offset of priority value bit field */
327  prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
328
329  /* disable (mask) main interrupt */
330  mpc5200.crit_pri_main_mask |= (0x80000000 >> SIU_MaskBit [irqLine]);
331
332  if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
333    /* disable external irq-pin */
334    mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
335  }
336
337  /* reset priority to lowest level (reset value) */
338  reg = (uint32_t *) (&(mpc5200.main_pri_1));
339  reg += (irqLine >> 3);
340  *reg &= ~(15 << (28 - (prio_index_offset << 2)));
341}
342
343static inline void BSP_disable_crit_irq_at_siu( rtems_vector_number
344                                               irqLine)
345{
346  uint8_t prio_index_offset;
347  uint32_t *reg;
348
349  prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
350
351  /* reset critical int priority to lowest level (reset value) */
352  reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
353  *reg &= ~(3 << (30 - (prio_index_offset << 1)));
354
355  if (irqLine == BSP_SIU_IRQ_IRQ1) {
356    /* disable external irq0-pin */
357    mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
358  }
359}
360
361/*
362 * This function enables a given siu interrupt
363 */
364rtems_status_code bsp_interrupt_vector_enable( rtems_vector_number irqLine)
365{
366  int base_index = get_siu_irq_base_index( irqLine);
367
368  if (is_siu_irq( irqLine)) {
369    rtems_interrupt_level level;
370
371    rtems_interrupt_disable( level);
372
373    switch (base_index) {
374      case BSP_PER_IRQ_LOWEST_OFFSET:
375        BSP_enable_per_irq_at_siu( irqLine);
376        break;
377      case BSP_MAIN_IRQ_LOWEST_OFFSET:
378        BSP_enable_main_irq_at_siu( irqLine);
379        break;
380      case BSP_CRIT_IRQ_LOWEST_OFFSET:
381        BSP_enable_crit_irq_at_siu( irqLine);
382        break;
383      default:
384        rtems_interrupt_enable( level);
385        printk( "No valid base index\n");
386        return RTEMS_INVALID_NUMBER;
387    }
388
389    rtems_interrupt_enable( level);
390  }
391
392  return RTEMS_SUCCESSFUL;
393}
394
395/*
396 * This function disables a given siu interrupt
397 */
398rtems_status_code bsp_interrupt_vector_disable( rtems_vector_number irqLine)
399{
400  int base_index = get_siu_irq_base_index( irqLine);
401
402  if (is_siu_irq( irqLine)) {
403    rtems_interrupt_level level;
404
405    rtems_interrupt_disable( level);
406
407    switch (base_index) {
408      case BSP_PER_IRQ_LOWEST_OFFSET:
409        BSP_disable_per_irq_at_siu( irqLine);
410        break;
411      case BSP_MAIN_IRQ_LOWEST_OFFSET:
412        BSP_disable_main_irq_at_siu( irqLine);
413        break;
414      case BSP_CRIT_IRQ_LOWEST_OFFSET:
415        BSP_disable_crit_irq_at_siu( irqLine);
416        break;
417      default:
418        rtems_interrupt_enable( level);
419        printk( "No valid base index\n");
420        return RTEMS_INVALID_NUMBER;
421    }
422
423    rtems_interrupt_enable( level);
424  }
425
426  return RTEMS_SUCCESSFUL;
427}
428
429#if (BENCHMARK_IRQ_PROCESSING == 0)
430void BSP_IRQ_Benchmarking_Reset( void)
431{
432}
433void BSP_IRQ_Benchmarking_Report( void)
434{
435}
436#else
437#include <stdio.h>
438uint64_t BSP_Starting_TBR;
439uint64_t BSP_Total_in_ISR;
440uint32_t BSP_ISR_Count;
441uint32_t BSP_Worst_ISR;
442
443#define BSP_COUNTED_IRQ 16
444uint32_t BSP_ISR_Count_Per [BSP_COUNTED_IRQ + 1];
445
446void BSP_IRQ_Benchmarking_Reset( void)
447{
448  int i;
449
450  BSP_Starting_TBR = PPC_Get_timebase_register();
451  BSP_Total_in_ISR = 0;
452  BSP_ISR_Count = 0;
453  BSP_Worst_ISR = 0;
454  for (i = 0; i < BSP_COUNTED_IRQ; i++)
455    BSP_ISR_Count_Per [i] = 0;
456}
457
458static const char *u64tostring( char *buffer, uint64_t v)
459{
460  sprintf( buffer, "%lld cycles %lld usecs", v, (v / 33));
461  return buffer;
462}
463
464void BSP_IRQ_Benchmarking_Report( void)
465{
466  uint64_t now;
467  char buffer [96];
468  int i;
469
470  now = PPC_Get_timebase_register();
471  printk( "Started at: %s\n", u64tostring( buffer, BSP_Starting_TBR));
472  printk( "Current   : %s\n", u64tostring( buffer, now));
473  printk( "System up : %s\n", u64tostring( buffer, now - BSP_Starting_TBR));
474  printk( "ISRs      : %d\n", BSP_ISR_Count);
475  printk( "ISRs ran  : %s\n", u64tostring( buffer, BSP_Total_in_ISR));
476  printk( "Worst ISR : %s\n", u64tostring( buffer, BSP_Worst_ISR));
477  for (i = 0; i < BSP_COUNTED_IRQ; i++)
478    printk( "IRQ %d: %d\n", i, BSP_ISR_Count_Per [i]);
479  printk( "Ticks     : %d\n", Clock_driver_ticks);
480}
481#endif
482
483/*
484 * High level IRQ handler called from shared_raw_irq_code_entry
485 */
486int C_dispatch_irq_handler(BSP_Exception_frame *frame, unsigned excNum)
487{
488  register unsigned int irq;
489  register unsigned int pmce;
490  register unsigned int crit_pri_main_mask,
491    per_mask;
492
493#if (ALLOW_IRQ_NESTING == 1)
494  uint32_t msr;
495#endif
496
497#if (BENCHMARK_IRQ_PROCESSING == 1)
498  uint64_t start,
499    stop,
500    thisTime;
501
502  start = PPC_Get_timebase_register();
503  BSP_ISR_Count++;
504  if (excNum < BSP_COUNTED_IRQ)
505    BSP_ISR_Count_Per [excNum]++;
506  else
507    printk( "not counting %d\n", excNum);
508#endif
509
510  switch (excNum) {
511      /*
512       * Handle decrementer interrupt
513       */
514    case ASM_DEC_VECTOR:
515
516      /* Dispatch interrupt handlers */
517      bsp_interrupt_handler_dispatch( BSP_DECREMENTER);
518
519      break;
520
521    case ASM_60X_SYSMGMT_VECTOR:
522
523      /* get the content of main interrupt status register */
524      pmce = mpc5200.pmce;
525
526      /* main interrupts may be routed to SMI, see bit SMI/INT select
527       * bit in main int. priorities
528       */
529      while (CHK_MSE_STICKY( pmce)) {
530
531        /* check for main interrupt sources (hirarchical order)
532         * -> LO_int indicates peripheral sources
533         */
534        if (CHK_MSE_STICKY( pmce)) {
535          /* get source of main interrupt */
536          irq = MSE_SOURCE( pmce);
537          switch (irq) {
538
539              /* irq1-3, RTC, GPIO, TMR0-7 detected (attention:
540               * slice timer 2 is always routed to SMI)
541               */
542            case 0:            /* slice timer 2 */
543            case 1:
544            case 2:
545            case 3:
546            case 5:
547            case 6:
548            case 7:
549            case 8:
550            case 9:
551            case 10:
552            case 11:
553            case 12:
554            case 13:
555            case 14:
556            case 15:
557            case 16:
558
559              /* add proper offset for main interrupts in
560               * the siu handler array
561               */
562              irq += BSP_MAIN_IRQ_LOWEST_OFFSET;
563
564              /* save original mask and disable all lower
565               * priorized main interrupts
566               */
567              crit_pri_main_mask = mpc5200.crit_pri_main_mask;
568              mpc5200.crit_pri_main_mask |= irqMaskTable [irq];
569
570#if (ALLOW_IRQ_NESTING == 1)
571              /* enable interrupt nesting */
572              msr = ppc_external_exceptions_enable();
573#endif
574
575              /* Dispatch interrupt handlers */
576              bsp_interrupt_handler_dispatch( irq);
577
578#if (ALLOW_IRQ_NESTING == 1)
579              /* disable interrupt nesting */
580              ppc_external_exceptions_disable( msr);
581#endif
582
583              /* restore original interrupt mask */
584              mpc5200.crit_pri_main_mask = crit_pri_main_mask;
585
586              break;
587
588              /* peripheral LO_int interrupt source detected */
589            case 4:
590
591              /* check for valid peripheral interrupt source */
592              if (CHK_PSE_STICKY( pmce)) {
593                /* get source of peripheral interrupt */
594                irq = PSE_SOURCE( pmce);
595
596                /* add proper offset for peripheral interrupts
597                 * in the siu handler array
598                 */
599                irq += BSP_PER_IRQ_LOWEST_OFFSET;
600
601                /* save original mask and disable all lower
602                 * priorized main interrupts
603                 */
604                per_mask = mpc5200.per_mask;
605                mpc5200.per_mask |= irqMaskTable [irq];
606
607#if (ALLOW_IRQ_NESTING == 1)
608                /* enable interrupt nesting */
609                msr = ppc_external_exceptions_enable();
610#endif
611
612                /* Dispatch interrupt handlers */
613                bsp_interrupt_handler_dispatch( irq);
614
615#if (ALLOW_IRQ_NESTING == 1)
616                /* disable interrupt nesting */
617                ppc_external_exceptions_disable( msr);
618#endif
619
620                /* restore original interrupt mask */
621                mpc5200.per_mask = per_mask;
622
623                /* force re-evaluation of peripheral interrupts */
624                CLR_PSE_STICKY( mpc5200.pmce);
625              } else {
626                /* this case may not occur: no valid peripheral
627                 * interrupt source
628                 */
629                printk( "No valid peripheral LO_int interrupt source\n");
630              }
631              break;
632              /* error: unknown interrupt source */
633            default:
634              printk( "Unknown peripheral LO_int interrupt source\n");
635              break;
636          }
637
638          /* force re-evaluation of main interrupts */
639          CLR_MSE_STICKY( mpc5200.pmce);
640        }
641
642        /* get the content of main interrupt status register */
643        pmce = mpc5200.pmce;
644      }
645      break;
646
647    case ASM_EXT_VECTOR:
648      /* get the content of main interrupt status register */
649      pmce = mpc5200.pmce;
650
651      /* critical interrupts may be routed to the core_int
652       * dependent on premature initialization, see bit 31 (CEbsH)
653       */
654      while ((CHK_CE_SHADOW( pmce) && CHK_CSE_STICKY( pmce))
655             || CHK_MSE_STICKY( pmce) || CHK_PSE_STICKY( pmce)) {
656
657        /* first: check for critical interrupt sources (hierarchical order)
658         * -> HI_int indicates peripheral sources
659         */
660        if (CHK_CE_SHADOW( pmce) && CHK_CSE_STICKY( pmce)) {
661          /* get source of critical interrupt */
662          irq = CSE_SOURCE( pmce);
663          switch (irq) {
664              /* irq0, slice timer 1 or ccs wakeup detected */
665            case 0:
666            case 1:
667            case 3:
668
669              /* add proper offset for critical interrupts in the siu
670               * handler array */
671              irq += BSP_CRIT_IRQ_LOWEST_OFFSET;
672
673              /* Dispatch interrupt handlers */
674              bsp_interrupt_handler_dispatch( irq);
675
676              break;
677
678              /* peripheral HI_int interrupt source detected */
679            case 2:
680              /* check for valid peripheral interrupt source */
681              if (CHK_PSE_STICKY( pmce)) {
682                /* get source of peripheral interrupt */
683                irq = PSE_SOURCE( pmce);
684
685                /* add proper offset for peripheral interrupts in the
686                 * siu handler array */
687                irq += BSP_PER_IRQ_LOWEST_OFFSET;
688
689                /* save original mask and disable all lower
690                 * priorized main interrupts */
691                per_mask = mpc5200.per_mask;
692                mpc5200.per_mask |= irqMaskTable [irq];
693
694#if (ALLOW_IRQ_NESTING == 1)
695                /* enable interrupt nesting */
696                msr = ppc_external_exceptions_enable();
697#endif
698
699                /* Dispatch interrupt handlers */
700                bsp_interrupt_handler_dispatch( irq);
701
702#if (ALLOW_IRQ_NESTING == 1)
703                /* disable interrupt nesting */
704                ppc_external_exceptions_disable( msr);
705#endif
706
707                /* restore original interrupt mask */
708                mpc5200.per_mask = per_mask;
709
710                /* force re-evaluation of peripheral interrupts */
711                CLR_PSE_STICKY( mpc5200.pmce);
712              } else {
713                /* this case may not occur: no valid peripheral
714                 * interrupt source */
715                printk( "No valid peripheral HI_int interrupt source\n");
716              }
717              break;
718            default:
719              /* error: unknown interrupt source */
720              printk( "Unknown HI_int interrupt source\n");
721              break;
722          }
723          /* force re-evaluation of critical interrupts */
724          CLR_CSE_STICKY( mpc5200.pmce);
725        }
726
727        /* second: check for main interrupt sources (hierarchical order)
728         * -> LO_int indicates peripheral sources */
729        if (CHK_MSE_STICKY( pmce)) {
730          /* get source of main interrupt */
731          irq = MSE_SOURCE( pmce);
732
733          switch (irq) {
734
735              /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer
736               * 2 is always routed to SMI) */
737            case 1:
738            case 2:
739            case 3:
740            case 5:
741            case 6:
742            case 7:
743            case 8:
744            case 9:
745            case 10:
746            case 11:
747            case 12:
748            case 13:
749            case 14:
750            case 15:
751            case 16:
752              /* add proper offset for main interrupts in the siu
753               * handler array */
754              irq += BSP_MAIN_IRQ_LOWEST_OFFSET;
755
756              /* save original mask and disable all lower priorized
757               * main interrupts*/
758              crit_pri_main_mask = mpc5200.crit_pri_main_mask;
759              mpc5200.crit_pri_main_mask |= irqMaskTable [irq];
760
761#if (ALLOW_IRQ_NESTING == 1)
762              /* enable interrupt nesting */
763              msr = ppc_external_exceptions_enable();
764#endif
765
766              /* Dispatch interrupt handlers */
767              bsp_interrupt_handler_dispatch( irq);
768
769#if (ALLOW_IRQ_NESTING == 1)
770              /* disable interrupt nesting */
771              ppc_external_exceptions_disable( msr);
772#endif
773
774              /* restore original interrupt mask */
775              mpc5200.crit_pri_main_mask = crit_pri_main_mask;
776              break;
777
778              /* peripheral LO_int interrupt source detected */
779            case 4:
780              /* check for valid peripheral interrupt source */
781              if (CHK_PSE_STICKY( pmce)) {
782                /* get source of peripheral interrupt */
783                irq = PSE_SOURCE( pmce);
784
785                /* add proper offset for peripheral interrupts in the siu
786                 * handler array */
787                irq += BSP_PER_IRQ_LOWEST_OFFSET;
788
789                /* save original mask and disable all lower priorized main
790                 * interrupts */
791                per_mask = mpc5200.per_mask;
792                mpc5200.per_mask |= irqMaskTable [irq];
793
794#if (ALLOW_IRQ_NESTING == 1)
795                /* enable interrupt nesting */
796                msr = ppc_external_exceptions_enable();
797#endif
798
799                /* Dispatch interrupt handlers */
800                bsp_interrupt_handler_dispatch( irq);
801
802#if (ALLOW_IRQ_NESTING == 1)
803                /* disable interrupt nesting */
804                ppc_external_exceptions_disable( msr);
805#endif
806
807                /* restore original interrupt mask */
808                mpc5200.per_mask = per_mask;
809
810                /* force re-evaluation of peripheral interrupts */
811                CLR_PSE_STICKY( mpc5200.pmce);
812              } else {
813                /* this case may not occur: no valid peripheral
814                 * interrupt source */
815                printk( "No valid peripheral LO_int interrupt source\n");
816              }
817              break;
818
819              /* error: unknown interrupt source */
820            default:
821              printk( "Unknown peripheral LO_int interrupt source\n");
822              break;
823          }
824          /* force re-evaluation of main interrupts */
825          CLR_MSE_STICKY( mpc5200.pmce);
826        }
827        /* get the content of main interrupt status register */
828        pmce = mpc5200.pmce;
829      }
830      break;
831
832    default:
833      printk( "Unknown processor exception\n");
834      break;
835
836  }                             /* end of switch( excNum) */
837
838#if (BENCHMARK_IRQ_PROCESSING == 1)
839  stop = PPC_Get_timebase_register();
840  thisTime = stop - start;
841  BSP_Total_in_ISR += thisTime;
842  if (thisTime > BSP_Worst_ISR)
843    BSP_Worst_ISR = thisTime;
844#endif
845
846  return 0;
847}
848
849/*
850 * setup irqMaskTable to support a priorized/nested interrupt environment
851 */
852void setup_irqMaskTable( void)
853{
854  rtems_irq_prio prio = 0;
855  uint32_t i = 0,
856    j = 0,
857    mask = 0;
858
859  /* set up the priority dependent masks for peripheral interrupts */
860  for (i = BSP_PER_IRQ_LOWEST_OFFSET; i <= BSP_PER_IRQ_MAX_OFFSET; i++) {
861    prio = irqPrioTable [i];
862    mask = 0;
863
864    for (j = BSP_PER_IRQ_LOWEST_OFFSET; j <= BSP_PER_IRQ_MAX_OFFSET; j++) {
865      if (prio > irqPrioTable [j]) {
866        mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET));
867      }
868
869      if ((prio == irqPrioTable [j]) && (j >= i)) {
870        mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET));
871      }
872    }
873
874    irqMaskTable [i] = mask;
875  }
876
877  /* set up the priority dependent masks for main interrupts */
878  for (i = BSP_MAIN_IRQ_LOWEST_OFFSET; i <= BSP_MAIN_IRQ_MAX_OFFSET; i++) {
879    prio = irqPrioTable [i];
880    mask = 0;
881
882    for (j = BSP_MAIN_IRQ_LOWEST_OFFSET; j <= BSP_MAIN_IRQ_MAX_OFFSET; j++) {
883      if (prio > irqPrioTable [j]) {
884        mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET));
885      }
886
887      if ((prio == irqPrioTable [j]) && (j >= i)) {
888        mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET));
889      }
890    }
891
892    irqMaskTable [i] = mask;
893  }
894}
895
896/*
897 * Initialize MPC5x00 SIU interrupt management
898 */
899void BSP_SIU_irq_init( void)
900{
901
902  /* disable all peripheral interrupts */
903  mpc5200.per_mask = 0xFFFFFC00;
904
905  /* peripheral interrupt priorities according to reset value */
906  mpc5200.per_pri_1 = 0xF0000000;
907  mpc5200.per_pri_2 = 0x00000000;
908  mpc5200.per_pri_3 = 0x00000000;
909
910  /* disable external interrupts IRQ0-4 / critical interrupts are routed to core_int */
911  mpc5200.ext_en_type = 0x0F000001;
912
913  /* disable main interrupts / crit. int. priorities according to reset values */
914  mpc5200.crit_pri_main_mask = 0x0001FFFF;
915
916  /* main priorities according to reset value */
917  mpc5200.main_pri_1 = 0;
918  mpc5200.main_pri_2 = 0;
919
920  /* reset all status indicators */
921  mpc5200.csa = 0x0001FFFF;
922  mpc5200.msa = 0x0001FFFF;
923  mpc5200.psa = 0x003FFFFF;
924  mpc5200.psa_be = 0x03000000;
925
926  setup_irqMaskTable();
927}
928
929rtems_status_code bsp_interrupt_facility_initialize( void)
930{
931  BSP_SIU_irq_init();
932
933  /* Install exception handler */
934  if (ppc_exc_set_handler( ASM_EXT_VECTOR, C_dispatch_irq_handler)) {
935    return RTEMS_IO_ERROR;
936  }
937  if (ppc_exc_set_handler( ASM_DEC_VECTOR, C_dispatch_irq_handler)) {
938    return RTEMS_IO_ERROR;
939  }
940  if (ppc_exc_set_handler( ASM_E300_SYSMGMT_VECTOR, C_dispatch_irq_handler)) {
941    return RTEMS_IO_ERROR;
942  }
943
944  return RTEMS_SUCCESSFUL;
945}
946
947void bsp_interrupt_handler_default( rtems_vector_number vector)
948{
949  if (vector != BSP_DECREMENTER) {
950    printk( "Spurious interrupt: 0x%08x\n", vector);
951  }
952}
Note: See TracBrowser for help on using the repository browser.