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

4.115
Last change on this file since ddd5640 was ddd5640, checked in by Sebastian Huber <sebastian.huber@…>, on 11/15/10 at 10:55:02

2010-11-12 Sebastian Huber <sebastian.huber@…>

  • make/custom/dp2.cfg, startup/linkcmds.dp2: New files.
  • Makefile.am, preinstall.am: Reflect change above. Install <bsp/utility.h>. Install BestComm? header files.
  • configure.ac: Changed BSP options.
  • include/mpc5200.h: Added module structures and register defines.
  • bestcomm/bestcomm_api.c, bestcomm/bestcomm_api.h, bestcomm/bestcomm_glue.c, bestcomm/bestcomm_glue.h, bestcomm/bestcomm_priv.h, bestcomm/load_task.c, bestcomm/tasksetup_bdtable.c, bestcomm/task_api/bestcomm_cntrl.h: C++ compatibility. Use special heap to manage the SRAM region. Use interrupt extension API. Fixed warnings.
  • console/console.c: Fixed console registration. Fixed warnings. Added GPS module registration.
  • ide/pcmcia_ide.h: Fixed clock value macros.
  • ide/pcmcia_ide.c: Update for BestComm? API changes. DP2 specific initialization. Removed zero loop in PIO receive function.
  • include/bsp.h: Added DP2 variant. Removed obsolete defines.
  • include/mscan-base.h, mscan/mscan-base.c: Use volatile qualifier. Format.
  • irq/irq.c: Fixed peripheral interrupt handling.
  • network_5200/network.c: Update for BestComm? API changes.
  • start/start.S: U-Boot fixes.
  • startup/cpuinit.c: Enable write-back cache strategy. Added special memory regions.
  • startup/linkcmds.brs5l: Fixed memory size.
  • Property mode set to 100644
File size: 25.8 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
483static void dispatch(uint32_t irq, uint32_t offset, volatile uint32_t *maskreg)
484{
485  #if (ALLOW_IRQ_NESTING == 1)
486    uint32_t msr;
487  #endif
488
489  uint32_t mask = *maskreg;
490
491  irq += offset;
492
493  *maskreg = mask | irqMaskTable [irq];
494
495  #if (ALLOW_IRQ_NESTING == 1)
496    msr = ppc_external_exceptions_enable();
497  #endif
498
499  bsp_interrupt_handler_dispatch(irq);
500
501  #if (ALLOW_IRQ_NESTING == 1)
502    ppc_external_exceptions_disable(msr);
503  #endif
504
505  *maskreg = mask;
506}
507
508/*
509 * High level IRQ handler called from shared_raw_irq_code_entry
510 */
511int C_dispatch_irq_handler(BSP_Exception_frame *frame, unsigned excNum)
512{
513  uint32_t irq;
514  uint32_t pmce;
515
516#if (BENCHMARK_IRQ_PROCESSING == 1)
517  uint64_t start,
518    stop,
519    thisTime;
520
521  start = PPC_Get_timebase_register();
522  BSP_ISR_Count++;
523  if (excNum < BSP_COUNTED_IRQ)
524    BSP_ISR_Count_Per [excNum]++;
525  else
526    printk( "not counting %d\n", excNum);
527#endif
528
529  switch (excNum) {
530      /*
531       * Handle decrementer interrupt
532       */
533    case ASM_DEC_VECTOR:
534
535      /* Dispatch interrupt handlers */
536      bsp_interrupt_handler_dispatch( BSP_DECREMENTER);
537
538      break;
539
540    case ASM_EXT_VECTOR:
541    case ASM_60X_SYSMGMT_VECTOR:
542      /* get the content of main interrupt status register */
543      pmce = mpc5200.pmce;
544
545      /* critical interrupts may be routed to the core_int
546       * dependent on premature initialization, see bit 31 (CEbsH)
547       */
548      while ((CHK_CE_SHADOW( pmce) && CHK_CSE_STICKY( pmce))
549             || CHK_MSE_STICKY( pmce) || CHK_PSE_STICKY( pmce)) {
550
551        /* first: check for critical interrupt sources (hierarchical order)
552         * -> HI_int indicates peripheral sources
553         */
554        if (CHK_CE_SHADOW( pmce) && CHK_CSE_STICKY( pmce)) {
555          /* get source of critical interrupt */
556          irq = CSE_SOURCE( pmce);
557          switch (irq) {
558              /* irq0, slice timer 1 or ccs wakeup detected */
559            case 0:
560            case 1:
561            case 3:
562
563              /* add proper offset for critical interrupts in the siu
564               * handler array */
565              irq += BSP_CRIT_IRQ_LOWEST_OFFSET;
566
567              /* Dispatch interrupt handlers */
568              bsp_interrupt_handler_dispatch( irq);
569
570              break;
571
572              /* peripheral HI_int interrupt source detected */
573            case 2:
574              /* check for valid peripheral interrupt source */
575              if (CHK_PSE_STICKY( pmce)) {
576                /* get source of peripheral interrupt */
577                irq = PSE_SOURCE( pmce);
578
579                dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
580
581                /* force re-evaluation of peripheral interrupts */
582                CLR_PSE_STICKY( mpc5200.pmce);
583              } else {
584                /* this case may not occur: no valid peripheral
585                 * interrupt source */
586                printk( "No valid peripheral HI_int interrupt source\n");
587              }
588              break;
589            default:
590              /* error: unknown interrupt source */
591              printk( "Unknown HI_int interrupt source\n");
592              break;
593          }
594          /* force re-evaluation of critical interrupts */
595          CLR_CSE_STICKY( mpc5200.pmce);
596        }
597
598        /* second: check for main interrupt sources (hierarchical order)
599         * -> LO_int indicates peripheral sources */
600        if (CHK_MSE_STICKY( pmce)) {
601          /* get source of main interrupt */
602          irq = MSE_SOURCE( pmce);
603
604          switch (irq) {
605
606              /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer
607               * 2 is always routed to SMI) */
608            case 0:
609            case 1:
610            case 2:
611            case 3:
612            case 5:
613            case 6:
614            case 7:
615            case 8:
616            case 9:
617            case 10:
618            case 11:
619            case 12:
620            case 13:
621            case 14:
622            case 15:
623            case 16:
624              dispatch(irq, BSP_MAIN_IRQ_LOWEST_OFFSET, &mpc5200.crit_pri_main_mask);
625              break;
626
627              /* peripheral LO_int interrupt source detected */
628            case 4:
629              /* check for valid peripheral interrupt source */
630              if (CHK_PSE_STICKY( pmce)) {
631                /* get source of peripheral interrupt */
632                irq = PSE_SOURCE( pmce);
633
634                dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
635
636                /* force re-evaluation of peripheral interrupts */
637                CLR_PSE_STICKY( mpc5200.pmce);
638              } else {
639                /* this case may not occur: no valid peripheral
640                 * interrupt source */
641                printk( "No valid peripheral LO_int interrupt source\n");
642              }
643              break;
644
645              /* error: unknown interrupt source */
646            default:
647              printk( "Unknown peripheral LO_int interrupt source\n");
648              break;
649          }
650          /* force re-evaluation of main interrupts */
651          CLR_MSE_STICKY( mpc5200.pmce);
652        }
653
654        if (CHK_PSE_STICKY( pmce)) {
655          /* get source of peripheral interrupt */
656          irq = PSE_SOURCE( pmce);
657
658          dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
659
660          /* force re-evaluation of peripheral interrupts */
661          CLR_PSE_STICKY( mpc5200.pmce);
662        }
663
664        /* get the content of main interrupt status register */
665        pmce = mpc5200.pmce;
666      }
667      break;
668
669    default:
670      printk( "Unknown processor exception\n");
671      break;
672
673  }                             /* end of switch( excNum) */
674
675#if (BENCHMARK_IRQ_PROCESSING == 1)
676  stop = PPC_Get_timebase_register();
677  thisTime = stop - start;
678  BSP_Total_in_ISR += thisTime;
679  if (thisTime > BSP_Worst_ISR)
680    BSP_Worst_ISR = thisTime;
681#endif
682
683  return 0;
684}
685
686/*
687 * setup irqMaskTable to support a priorized/nested interrupt environment
688 */
689void setup_irqMaskTable( void)
690{
691  rtems_irq_prio prio = 0;
692  uint32_t i = 0,
693    j = 0,
694    mask = 0;
695
696  /* set up the priority dependent masks for peripheral interrupts */
697  for (i = BSP_PER_IRQ_LOWEST_OFFSET; i <= BSP_PER_IRQ_MAX_OFFSET; i++) {
698    prio = irqPrioTable [i];
699    mask = 0;
700
701    for (j = BSP_PER_IRQ_LOWEST_OFFSET; j <= BSP_PER_IRQ_MAX_OFFSET; j++) {
702      if (prio > irqPrioTable [j]) {
703        mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET));
704      }
705
706      if ((prio == irqPrioTable [j]) && (j >= i)) {
707        mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET));
708      }
709    }
710
711    irqMaskTable [i] = mask;
712  }
713
714  /* set up the priority dependent masks for main interrupts */
715  for (i = BSP_MAIN_IRQ_LOWEST_OFFSET; i <= BSP_MAIN_IRQ_MAX_OFFSET; i++) {
716    prio = irqPrioTable [i];
717    mask = 0;
718
719    for (j = BSP_MAIN_IRQ_LOWEST_OFFSET; j <= BSP_MAIN_IRQ_MAX_OFFSET; j++) {
720      if (prio > irqPrioTable [j]) {
721        mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET));
722      }
723
724      if ((prio == irqPrioTable [j]) && (j >= i)) {
725        mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET));
726      }
727    }
728
729    irqMaskTable [i] = mask;
730  }
731}
732
733/*
734 * Initialize MPC5x00 SIU interrupt management
735 */
736void BSP_SIU_irq_init( void)
737{
738
739  /* disable all peripheral interrupts */
740  mpc5200.per_mask = 0xFFFFFC00;
741
742  /* peripheral interrupt priorities according to reset value */
743  mpc5200.per_pri_1 = 0xF0000000;
744  mpc5200.per_pri_2 = 0x00000000;
745  mpc5200.per_pri_3 = 0x00000000;
746
747  /* disable external interrupts IRQ0-4 / critical interrupts are routed to core_int */
748  mpc5200.ext_en_type = 0x0F000001;
749
750  /* disable main interrupts / crit. int. priorities according to reset values */
751  mpc5200.crit_pri_main_mask = 0x0001FFFF;
752
753  /* main priorities according to reset value */
754  mpc5200.main_pri_1 = 0;
755  mpc5200.main_pri_2 = 0;
756
757  /* reset all status indicators */
758  mpc5200.csa = 0x0001FFFF;
759  mpc5200.msa = 0x0001FFFF;
760  mpc5200.psa = 0x003FFFFF;
761  mpc5200.psa_be = 0x03000000;
762
763  setup_irqMaskTable();
764}
765
766rtems_status_code bsp_interrupt_facility_initialize( void)
767{
768  BSP_SIU_irq_init();
769
770  /* Install exception handler */
771  if (ppc_exc_set_handler( ASM_EXT_VECTOR, C_dispatch_irq_handler)) {
772    return RTEMS_IO_ERROR;
773  }
774  if (ppc_exc_set_handler( ASM_DEC_VECTOR, C_dispatch_irq_handler)) {
775    return RTEMS_IO_ERROR;
776  }
777  if (ppc_exc_set_handler( ASM_E300_SYSMGMT_VECTOR, C_dispatch_irq_handler)) {
778    return RTEMS_IO_ERROR;
779  }
780
781  return RTEMS_SUCCESSFUL;
782}
783
784void bsp_interrupt_handler_default( rtems_vector_number vector)
785{
786  if (vector != BSP_DECREMENTER) {
787    printk( "Spurious interrupt: 0x%08x\n", vector);
788  }
789}
Note: See TracBrowser for help on using the repository browser.