source: rtems/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c @ 82bd8d9d

4.104.114.9
Last change on this file since 82bd8d9d was 82bd8d9d, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on Sep 3, 2008 at 3:39:03 PM

Converted to use shared

exception and interrupt code.

  • 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 <libcpu/raw_exception.h>
80
81#include <bsp.h>
82#include <bsp/irq.h>
83#include <bsp/vectors.h>
84#include <bsp/ppc_exc_bspsupp.h>
85#include <bsp/irq-generic.h>
86#include <bsp/mpc5200.h>
87
88/*
89 * bit in the SIU mask registers (PPC bit numbering) that should
90 * be set to enable the relevant interrupt, mask of 32 is for unused entries
91 *
92 */
93const static unsigned int SIU_MaskBit [BSP_SIU_IRQ_NUMBER] = {
94  0, 1, 2, 3,                   /* smart_comm, psc1, psc2, psc3            */
95  4, 5, 6, 7,                   /* irda/psc6, eth, usb, ata                */
96  8, 9, 10, 11,                 /* pci_ctrl, pci_sc_rx, pci_sc_tx, psc4    */
97  12, 13, 14, 15,               /* psc5,spi_modf, spi_spif, i2c1           */
98  16, 17, 18, 19,               /* i2c, can1, can2, ir_rx                  */
99  20, 21, 15, 16,               /* ir_rx, xlb_arb, slice_tim2, irq1,       */
100  17, 18, 19, 20,               /* irq2, irq3, lo_int, rtc_pint            */
101  21, 22, 23, 24,               /* rtc_sint, gpio_std, gpio_wkup, tmr0     */
102  25, 26, 27, 28,               /* tmr1, tmr2, tmr3, tmr4                  */
103  29, 30, 31, 32,               /* tmr5, tmr6, tmr7, res                   */
104  32, 32, 32                    /* res, res, res                           */
105};
106
107static unsigned char irqPrioTable [BSP_SIU_IRQ_NUMBER] = {
108/* per. int. priorities (0-7) / 4bit coding / msb is HI/LO selection               */
109/* msb = 0 -> non-critical per. int. is routed to main int. (LO_int)               */
110/* msb = 1 -> critical per. int. is routed to critical int. (HI_int)               */
111  0xF, 0, 0, 0,                 /* smart_comm (do not change!), psc1, psc2, psc3             */
112  0, 0, 0, 0,                   /* irda, eth, usb, ata                                       */
113  0, 0, 0, 0,                   /* pci_ctrl, pci_sc_rx, pci_sc_tx, res                       */
114  0, 0, 0, 0,                   /* res, spi_modf, spi_spif, i2c1                             */
115  0, 0, 0, 0,                   /* i2c, can1, can2, ir_rx                                    */
116  0, 0,                         /* ir_rx, xlb_arb                                            */
117/* main interrupt priorities (0-7) / 4bit coding / msb is INT/SMI selection        */
118/* msb = 0 -> main int. is routed to processor INT (low vector base 0x500 )        */
119/* msb = 1 -> main int. is routed to processor SMI (low vector base 0x1400 )       */
120  0, 0,                         /* slice_tim2, irq1                                          */
121  0, 0, 0, 0,                   /* irq2, irq3, lo_int, rtc_pint                              */
122  0, 0, 0, 0,                   /* rtc_sint, gpio_std, gpio_wkup, tmr0                       */
123  0, 0, 0, 0,                   /* tmr1, tmr2, tmr3, tmr4                                    */
124  0, 0, 0,                      /* tmr5, tmr6, tmr7                                          */
125  /* critical interrupt priorities (0-3) / 2bit coding / no special purpose of msb */
126  0,                            /* irq0                                                      */
127  0, 0, 0                       /* slice_tim1, hi_int, ccs_wkup                              */
128};
129
130static uint32_t irqMaskTable [BSP_PER_IRQ_NUMBER + BSP_MAIN_IRQ_NUMBER];
131
132/*
133 * Check if symbolic IRQ name is a Processor IRQ
134 */
135static inline bool is_processor_irq( rtems_vector_number irqLine)
136{
137
138  return ((irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET)
139    && (irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET));
140}
141
142/*
143 * Check for SIU IRQ and return base index
144 */
145static inline bool is_siu_irq( rtems_vector_number irqLine)
146{
147
148  return ((irqLine <= BSP_SIU_IRQ_MAX_OFFSET)
149    && (irqLine >= BSP_SIU_IRQ_LOWEST_OFFSET));
150}
151
152/*
153 * Check for SIU IRQ and return base index
154 */
155static inline int get_siu_irq_base_index( rtems_vector_number irqLine)
156{
157  if (irqLine <= BSP_PER_IRQ_MAX_OFFSET)
158    return BSP_PER_IRQ_LOWEST_OFFSET;
159
160  if (irqLine <= BSP_MAIN_IRQ_MAX_OFFSET)
161    return BSP_MAIN_IRQ_LOWEST_OFFSET;
162
163  if (irqLine <= BSP_CRIT_IRQ_MAX_OFFSET)
164    return BSP_CRIT_IRQ_LOWEST_OFFSET;
165
166  return -1;
167}
168
169static inline void BSP_enable_per_irq_at_siu(
170  rtems_vector_number irqLine
171)
172{
173  uint8_t lo_hi_ind = 0,
174    prio_index_offset;
175  uint32_t *reg;
176  volatile uint32_t per_pri_1,
177    main_pri_1,
178    crit_pri_main_mask,
179    per_mask;
180
181  /* calculate the index offset of priority value bit field */
182  prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
183
184  /* set interrupt priorities */
185  if (irqPrioTable [irqLine] <= 15) {
186
187    /* set peripheral int priority */
188    reg = (uint32_t *) (&(mpc5200.per_pri_1));
189
190    /* choose proper register */
191    reg += (irqLine >> 3);
192
193    /* set priority as given in priority table */
194    *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2)));
195
196    /* test msb (hash-bit) and set LO_/HI_int indicator */
197    if ((lo_hi_ind = (irqPrioTable [irqLine] >> 3))) {
198
199      /* set critical HI_int priority */
200      reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
201      *reg |= (irqPrioTable [BSP_SIU_IRQ_HI_INT] << 26);
202
203      /*
204       * critical interrupt handling for the 603le core is not
205       * yet supported, routing of critical interrupts is forced
206       * to core_int (bit 31 / CEb)
207       */
208      mpc5200.ext_en_type |= 1;
209
210    } else {
211      if (irqPrioTable [irqLine] <= 15) {
212        /* set main LO_int priority */
213        reg = (uint32_t *) (&(mpc5200.main_pri_1));
214        *reg |= (irqPrioTable [BSP_SIU_IRQ_LO_INT] << 16);
215      }
216    }
217  }
218
219  /* if LO_int ind., enable (unmask) main interrupt */
220  if (!lo_hi_ind) {
221    mpc5200.crit_pri_main_mask &=
222      ~(0x80000000 >> SIU_MaskBit [BSP_SIU_IRQ_LO_INT]);
223  }
224
225  /* enable (unmask) peripheral interrupt */
226  mpc5200.per_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]);
227
228  main_pri_1 = mpc5200.main_pri_1;
229  crit_pri_main_mask = mpc5200.crit_pri_main_mask;
230  per_pri_1 = mpc5200.per_pri_1;
231  per_mask = mpc5200.per_mask;
232
233}
234
235static inline void BSP_enable_main_irq_at_siu(
236  rtems_vector_number irqLine
237)
238{
239
240  uint8_t prio_index_offset;
241  uint32_t *reg;
242
243  /* calculate the index offset of priority value bit field */
244  prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
245
246  /* set main interrupt priority */
247  if (irqPrioTable [irqLine] <= 15) {
248
249    /* set main int priority */
250    reg = (uint32_t *) (&(mpc5200.main_pri_1));
251
252    /* choose proper register */
253    reg += (irqLine >> 3);
254
255    /* set priority as given in priority table */
256    *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2)));
257
258    if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
259      /* enable external irq-pin */
260      mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
261    }
262  }
263
264  /* enable (unmask) main interrupt */
265  mpc5200.crit_pri_main_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]);
266
267}
268
269static inline void BSP_enable_crit_irq_at_siu(
270  rtems_vector_number irqLine
271)
272{
273  uint8_t prio_index_offset;
274  uint32_t *reg;
275
276  prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
277
278  /*
279   * critical interrupt handling for the 603Le core is not
280   * yet supported, routing of critical interrupts is forced
281   * to core_int (bit 31 / CEb)
282   */
283  mpc5200.ext_en_type |= 1;
284
285  /* set critical interrupt priorities */
286  if (irqPrioTable [irqLine] <= 3) {
287
288    /* choose proper register */
289    reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
290
291    /* set priority as given in priority table */
292    *reg |= (irqPrioTable [irqLine] << (30 - (prio_index_offset << 1)));
293
294    /* external irq0-pin */
295    if (irqLine == BSP_SIU_IRQ_IRQ1) {
296      /* enable external irq-pin */
297      mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
298    }
299  }
300}
301
302static inline void BSP_disable_per_irq_at_siu(
303  rtems_vector_number irqLine
304)
305{
306  uint8_t prio_index_offset;
307  uint32_t *reg;
308
309  /* calculate the index offset of priority value bit field */
310  prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
311
312  /* disable (mask) peripheral interrupt */
313  mpc5200.per_mask |= (0x80000000 >> SIU_MaskBit [irqLine]);
314
315  /* reset priority to lowest level (reset value) */
316  reg = (uint32_t *) (&(mpc5200.per_pri_1));
317  reg += (irqLine >> 3);
318  *reg &= ~(15 << (28 - (prio_index_offset << 2)));
319}
320
321static inline void BSP_disable_main_irq_at_siu(
322  rtems_vector_number irqLine
323)
324{
325  uint8_t prio_index_offset;
326  uint32_t *reg;
327
328  /* calculate the index offset of priority value bit field */
329  prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
330
331  /* disable (mask) main interrupt */
332  mpc5200.crit_pri_main_mask |= (0x80000000 >> SIU_MaskBit [irqLine]);
333
334  if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
335    /* disable external irq-pin */
336    mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
337  }
338
339  /* reset priority to lowest level (reset value) */
340  reg = (uint32_t *) (&(mpc5200.main_pri_1));
341  reg += (irqLine >> 3);
342  *reg &= ~(15 << (28 - (prio_index_offset << 2)));
343}
344
345static inline void BSP_disable_crit_irq_at_siu( rtems_vector_number
346                                               irqLine)
347{
348  uint8_t prio_index_offset;
349  uint32_t *reg;
350
351  prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
352
353  /* reset critical int priority to lowest level (reset value) */
354  reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
355  *reg &= ~(3 << (30 - (prio_index_offset << 1)));
356
357  if (irqLine == BSP_SIU_IRQ_IRQ1) {
358    /* disable external irq0-pin */
359    mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
360  }
361}
362
363/*
364 * This function enables a given siu interrupt
365 */
366rtems_status_code bsp_interrupt_vector_enable( rtems_vector_number irqLine)
367{
368  int base_index = get_siu_irq_base_index( irqLine);
369
370  if (is_siu_irq( irqLine)) {
371    rtems_interrupt_level level;
372
373    rtems_interrupt_disable( level);
374
375    switch (base_index) {
376      case BSP_PER_IRQ_LOWEST_OFFSET:
377        BSP_enable_per_irq_at_siu( irqLine);
378        break;
379      case BSP_MAIN_IRQ_LOWEST_OFFSET:
380        BSP_enable_main_irq_at_siu( irqLine);
381        break;
382      case BSP_CRIT_IRQ_LOWEST_OFFSET:
383        BSP_enable_crit_irq_at_siu( irqLine);
384        break;
385      default:
386        rtems_interrupt_enable( level);
387        printk( "No valid base index\n");
388        return RTEMS_INVALID_NUMBER;
389    }
390
391    rtems_interrupt_enable( level);
392  }
393
394  return RTEMS_SUCCESSFUL;
395}
396
397/*
398 * This function disables a given siu interrupt
399 */
400rtems_status_code bsp_interrupt_vector_disable( rtems_vector_number irqLine)
401{
402  int base_index = get_siu_irq_base_index( irqLine);
403
404  if (is_siu_irq( irqLine)) {
405    rtems_interrupt_level level;
406
407    rtems_interrupt_disable( level);
408
409    switch (base_index) {
410      case BSP_PER_IRQ_LOWEST_OFFSET:
411        BSP_disable_per_irq_at_siu( irqLine);
412        break;
413      case BSP_MAIN_IRQ_LOWEST_OFFSET:
414        BSP_disable_main_irq_at_siu( irqLine);
415        break;
416      case BSP_CRIT_IRQ_LOWEST_OFFSET:
417        BSP_disable_crit_irq_at_siu( irqLine);
418        break;
419      default:
420        rtems_interrupt_enable( level);
421        printk( "No valid base index\n");
422        return RTEMS_INVALID_NUMBER;
423    }
424
425    rtems_interrupt_enable( level);
426  }
427
428  return RTEMS_SUCCESSFUL;
429}
430
431#if (BENCHMARK_IRQ_PROCESSING == 0)
432void BSP_IRQ_Benchmarking_Reset( void)
433{
434}
435void BSP_IRQ_Benchmarking_Report( void)
436{
437}
438#else
439#include <stdio.h>
440uint64_t BSP_Starting_TBR;
441uint64_t BSP_Total_in_ISR;
442uint32_t BSP_ISR_Count;
443uint32_t BSP_Worst_ISR;
444
445#define BSP_COUNTED_IRQ 16
446uint32_t BSP_ISR_Count_Per [BSP_COUNTED_IRQ + 1];
447
448void BSP_IRQ_Benchmarking_Reset( void)
449{
450  int i;
451
452  BSP_Starting_TBR = PPC_Get_timebase_register();
453  BSP_Total_in_ISR = 0;
454  BSP_ISR_Count = 0;
455  BSP_Worst_ISR = 0;
456  for (i = 0; i < BSP_COUNTED_IRQ; i++)
457    BSP_ISR_Count_Per [i] = 0;
458}
459
460static const char *u64tostring( char *buffer, uint64_t v)
461{
462  sprintf( buffer, "%lld cycles %lld usecs", v, (v / 33));
463  return buffer;
464}
465
466void BSP_IRQ_Benchmarking_Report( void)
467{
468  uint64_t now;
469  char buffer [96];
470  int i;
471
472  now = PPC_Get_timebase_register();
473  printk( "Started at: %s\n", u64tostring( buffer, BSP_Starting_TBR));
474  printk( "Current   : %s\n", u64tostring( buffer, now));
475  printk( "System up : %s\n", u64tostring( buffer, now - BSP_Starting_TBR));
476  printk( "ISRs      : %d\n", BSP_ISR_Count);
477  printk( "ISRs ran  : %s\n", u64tostring( buffer, BSP_Total_in_ISR));
478  printk( "Worst ISR : %s\n", u64tostring( buffer, BSP_Worst_ISR));
479  for (i = 0; i < BSP_COUNTED_IRQ; i++)
480    printk( "IRQ %d: %d\n", i, BSP_ISR_Count_Per [i]);
481  printk( "Ticks     : %d\n", Clock_driver_ticks);
482}
483#endif
484
485/*
486 * High level IRQ handler called from shared_raw_irq_code_entry
487 */
488int C_dispatch_irq_handler( CPU_Interrupt_frame * frame, unsigned int excNum)
489{
490  register unsigned int irq;
491  register unsigned int pmce;
492  register unsigned int crit_pri_main_mask,
493    per_mask;
494
495  uint32_t msr;
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.