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

5
Last change on this file since c6810c8 was c6810c8, checked in by Sebastian Huber <sebastian.huber@…>, on 06/19/17 at 12:09:28

bsps: Improve interrupt vector enable/disable API

Change bsp_interrupt_vector_enable() and bsp_interrupt_vector_disable()
to not return a status code. Add bsp_interrupt_assert() and use it to
validate the vector number in the vector enable/disable implementations.

  • Property mode set to 100644
File size: 24.1 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.org/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 the file LICENSE in this distribution or at     */
52/*   http://www.rtems.org/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 <inttypes.h>
77
78#include <rtems.h>
79
80#include <libcpu/powerpc-utility.h>
81#include <bsp/vectors.h>
82
83#include <bsp.h>
84#include <bsp/irq.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
177  /* calculate the index offset of priority value bit field */
178  prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
179
180  /* set interrupt priorities */
181  if (irqPrioTable [irqLine] <= 15) {
182
183    /* set peripheral int priority */
184    reg = (uint32_t *) (&(mpc5200.per_pri_1));
185
186    /* choose proper register */
187    reg += (irqLine >> 3);
188
189    /* set priority as given in priority table */
190    *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2)));
191
192    /* test msb (hash-bit) and set LO_/HI_int indicator */
193    if ((lo_hi_ind = (irqPrioTable [irqLine] >> 3))) {
194
195      /* set critical HI_int priority */
196      reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
197      *reg |= (irqPrioTable [BSP_SIU_IRQ_HI_INT] << 26);
198
199      /*
200       * critical interrupt handling for the 603le core is not
201       * yet supported, routing of critical interrupts is forced
202       * to core_int (bit 31 / CEb)
203       */
204      mpc5200.ext_en_type |= 1;
205
206    } else {
207      if (irqPrioTable [irqLine] <= 15) {
208        /* set main LO_int priority */
209        reg = (uint32_t *) (&(mpc5200.main_pri_1));
210        *reg |= (irqPrioTable [BSP_SIU_IRQ_LO_INT] << 16);
211      }
212    }
213  }
214
215  /* if LO_int ind., enable (unmask) main interrupt */
216  if (!lo_hi_ind) {
217    mpc5200.crit_pri_main_mask &=
218      ~(0x80000000 >> SIU_MaskBit [BSP_SIU_IRQ_LO_INT]);
219  }
220
221  /* enable (unmask) peripheral interrupt */
222  mpc5200.per_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]);
223
224  /* FIXME: Why? */
225  mpc5200.main_pri_1;
226  mpc5200.crit_pri_main_mask;
227  mpc5200.per_pri_1;
228  mpc5200.per_mask;
229}
230
231static inline void BSP_enable_main_irq_at_siu(
232  rtems_vector_number irqLine
233)
234{
235
236  uint8_t prio_index_offset;
237  uint32_t *reg;
238
239  /* calculate the index offset of priority value bit field */
240  prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
241
242  /* set main interrupt priority */
243  if (irqPrioTable [irqLine] <= 15) {
244
245    /* set main int priority */
246    reg = (uint32_t *) (&(mpc5200.main_pri_1));
247
248    /* choose proper register */
249    reg += (irqLine >> 3);
250
251    /* set priority as given in priority table */
252    *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2)));
253
254    if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
255      /* enable external irq-pin */
256      mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
257    }
258  }
259
260  /* enable (unmask) main interrupt */
261  mpc5200.crit_pri_main_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]);
262
263}
264
265static inline void BSP_enable_crit_irq_at_siu(
266  rtems_vector_number irqLine
267)
268{
269  uint8_t prio_index_offset;
270  uint32_t *reg;
271
272  prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
273
274  /*
275   * critical interrupt handling for the 603Le core is not
276   * yet supported, routing of critical interrupts is forced
277   * to core_int (bit 31 / CEb)
278   */
279  mpc5200.ext_en_type |= 1;
280
281  /* set critical interrupt priorities */
282  if (irqPrioTable [irqLine] <= 3) {
283
284    /* choose proper register */
285    reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
286
287    /* set priority as given in priority table */
288    *reg |= (irqPrioTable [irqLine] << (30 - (prio_index_offset << 1)));
289
290    /* external irq0-pin */
291    if (irqLine == BSP_SIU_IRQ_IRQ1) {
292      /* enable external irq-pin */
293      mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
294    }
295  }
296}
297
298static inline void BSP_disable_per_irq_at_siu(
299  rtems_vector_number irqLine
300)
301{
302  uint8_t prio_index_offset;
303  uint32_t *reg;
304
305  /* calculate the index offset of priority value bit field */
306  prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
307
308  /* disable (mask) peripheral interrupt */
309  mpc5200.per_mask |= (0x80000000 >> SIU_MaskBit [irqLine]);
310
311  /* reset priority to lowest level (reset value) */
312  reg = (uint32_t *) (&(mpc5200.per_pri_1));
313  reg += (irqLine >> 3);
314  *reg &= ~(15 << (28 - (prio_index_offset << 2)));
315}
316
317static inline void BSP_disable_main_irq_at_siu(
318  rtems_vector_number irqLine
319)
320{
321  uint8_t prio_index_offset;
322  uint32_t *reg;
323
324  /* calculate the index offset of priority value bit field */
325  prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
326
327  /* disable (mask) main interrupt */
328  mpc5200.crit_pri_main_mask |= (0x80000000 >> SIU_MaskBit [irqLine]);
329
330  if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
331    /* disable external irq-pin */
332    mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
333  }
334
335  /* reset priority to lowest level (reset value) */
336  reg = (uint32_t *) (&(mpc5200.main_pri_1));
337  reg += (irqLine >> 3);
338  *reg &= ~(15 << (28 - (prio_index_offset << 2)));
339}
340
341static inline void BSP_disable_crit_irq_at_siu( rtems_vector_number
342                                               irqLine)
343{
344  uint8_t prio_index_offset;
345  uint32_t *reg;
346
347  prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
348
349  /* reset critical int priority to lowest level (reset value) */
350  reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
351  *reg &= ~(3 << (30 - (prio_index_offset << 1)));
352
353  if (irqLine == BSP_SIU_IRQ_IRQ1) {
354    /* disable external irq0-pin */
355    mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
356  }
357}
358
359/*
360 * This function enables a given siu interrupt
361 */
362void bsp_interrupt_vector_enable( rtems_vector_number vector)
363{
364  int base_index = get_siu_irq_base_index( vector);
365
366  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
367
368  if (is_siu_irq( vector)) {
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( vector);
376        break;
377      case BSP_MAIN_IRQ_LOWEST_OFFSET:
378        BSP_enable_main_irq_at_siu( vector);
379        break;
380      case BSP_CRIT_IRQ_LOWEST_OFFSET:
381        BSP_enable_crit_irq_at_siu( vector);
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
393/*
394 * This function disables a given siu interrupt
395 */
396void bsp_interrupt_vector_disable( rtems_vector_number vector)
397{
398  int base_index = get_siu_irq_base_index( vector);
399
400  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
401
402  if (is_siu_irq( vector)) {
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( vector);
410        break;
411      case BSP_MAIN_IRQ_LOWEST_OFFSET:
412        BSP_disable_main_irq_at_siu( vector);
413        break;
414      case BSP_CRIT_IRQ_LOWEST_OFFSET:
415        BSP_disable_crit_irq_at_siu( vector);
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
427#if (BENCHMARK_IRQ_PROCESSING == 0)
428void BSP_IRQ_Benchmarking_Reset( void)
429{
430}
431void BSP_IRQ_Benchmarking_Report( void)
432{
433}
434#else
435#include <stdio.h>
436uint64_t BSP_Starting_TBR;
437uint64_t BSP_Total_in_ISR;
438uint32_t BSP_ISR_Count;
439uint32_t BSP_Worst_ISR;
440
441#define BSP_COUNTED_IRQ 16
442uint32_t BSP_ISR_Count_Per [BSP_COUNTED_IRQ + 1];
443
444void BSP_IRQ_Benchmarking_Reset( void)
445{
446  int i;
447
448  BSP_Starting_TBR = PPC_Get_timebase_register();
449  BSP_Total_in_ISR = 0;
450  BSP_ISR_Count = 0;
451  BSP_Worst_ISR = 0;
452  for (i = 0; i < BSP_COUNTED_IRQ; i++)
453    BSP_ISR_Count_Per [i] = 0;
454}
455
456static const char *u64tostring( char *buffer, uint64_t v)
457{
458  sprintf( buffer, "%lld cycles %lld usecs", v, (v / 33));
459  return buffer;
460}
461
462void BSP_IRQ_Benchmarking_Report( void)
463{
464  uint64_t now;
465  char buffer [96];
466  int i;
467
468  now = PPC_Get_timebase_register();
469  printk( "Started at: %s\n", u64tostring( buffer, BSP_Starting_TBR));
470  printk( "Current   : %s\n", u64tostring( buffer, now));
471  printk( "System up : %s\n", u64tostring( buffer, now - BSP_Starting_TBR));
472  printk( "ISRs      : %d\n", BSP_ISR_Count);
473  printk( "ISRs ran  : %s\n", u64tostring( buffer, BSP_Total_in_ISR));
474  printk( "Worst ISR : %s\n", u64tostring( buffer, BSP_Worst_ISR));
475  for (i = 0; i < BSP_COUNTED_IRQ; i++)
476    printk( "IRQ %d: %d\n", i, BSP_ISR_Count_Per [i]);
477  printk( "Ticks     : %d\n", Clock_driver_ticks);
478}
479#endif
480
481static void dispatch(uint32_t irq, uint32_t offset, volatile uint32_t *maskreg)
482{
483  #if (ALLOW_IRQ_NESTING == 1)
484    uint32_t msr;
485    uint32_t mask = *maskreg;
486  #endif
487
488  irq += offset;
489
490  #if (ALLOW_IRQ_NESTING == 1)
491    *maskreg = mask | irqMaskTable [irq];
492    /* Make sure that the write operation completed (cache inhibited area) */
493    *maskreg;
494    msr = ppc_external_exceptions_enable();
495  #endif
496
497  bsp_interrupt_handler_dispatch(irq);
498
499  #if (ALLOW_IRQ_NESTING == 1)
500    ppc_external_exceptions_disable(msr);
501    *maskreg = mask;
502  #endif
503}
504
505/*
506 * High level IRQ handler called from shared_raw_irq_code_entry
507 */
508static int C_dispatch_irq_handler(BSP_Exception_frame *frame, unsigned excNum)
509{
510  uint32_t irq;
511  uint32_t pmce;
512
513#if (BENCHMARK_IRQ_PROCESSING == 1)
514  uint64_t start,
515    stop,
516    thisTime;
517
518  start = PPC_Get_timebase_register();
519  BSP_ISR_Count++;
520  if (excNum < BSP_COUNTED_IRQ)
521    BSP_ISR_Count_Per [excNum]++;
522  else
523    printk( "not counting %d\n", excNum);
524#endif
525
526  /* get the content of main interrupt status register */
527  pmce = mpc5200.pmce;
528
529  /* critical interrupts are routed to the core_int, see premature
530   * initialization
531   */
532  while ((pmce & (PMCE_CSE_STICKY | PMCE_MSE_STICKY)) != 0) {
533    /* first: check for critical interrupt sources (hierarchical order)
534     * -> HI_int indicates peripheral sources
535     */
536    if ((pmce & PMCE_CSE_STICKY) != 0) {
537      /* get source of critical interrupt */
538      irq = PMCE_CSE_SOURCE(pmce);
539
540      switch (irq) {
541          /* peripheral HI_int interrupt source detected */
542        case 2:
543          /* check for valid peripheral interrupt source */
544          if ((pmce & PMCE_PSE_STICKY) != 0) {
545            /* get source of peripheral interrupt */
546            irq = PMCE_PSE_SOURCE(pmce);
547
548            dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
549          } else {
550            /* this case may not occur: no valid peripheral
551             * interrupt source */
552            printk( "No valid peripheral HI_int interrupt source\n");
553          }
554          break;
555
556          /* irq0, slice timer 1 or ccs wakeup detected */
557        case 0:
558        case 1:
559        case 3:
560
561          /* add proper offset for critical interrupts in the siu
562           * handler array */
563          irq += BSP_CRIT_IRQ_LOWEST_OFFSET;
564
565          /* Dispatch interrupt handlers */
566          bsp_interrupt_handler_dispatch( irq);
567
568          break;
569
570        default:
571          /* error: unknown interrupt source */
572          printk( "Unknown HI_int interrupt source\n");
573          break;
574      }
575    }
576
577    /* second: check for main interrupt sources (hierarchical order)
578     * -> LO_int indicates peripheral sources */
579    if ((pmce & PMCE_MSE_STICKY) != 0) {
580      /* get source of main interrupt */
581      irq = PMCE_MSE_SOURCE(pmce);
582
583      if (irq == 4) {
584          /* peripheral LO_int interrupt source detected */
585          /* check for valid peripheral interrupt source */
586          if ((pmce & PMCE_PSE_STICKY) != 0) {
587            /* get source of peripheral interrupt */
588            irq = PMCE_PSE_SOURCE(pmce);
589
590            dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
591          } else {
592            /* this case may not occur: no valid peripheral
593             * interrupt source */
594            printk( "No valid peripheral LO_int interrupt source\n");
595          }
596      } else if (irq <= 16) {
597          /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer
598           * 2 is always routed to SMI) */
599          dispatch(irq, BSP_MAIN_IRQ_LOWEST_OFFSET, &mpc5200.crit_pri_main_mask);
600      } else {
601          /* error: unknown interrupt source */
602          printk( "Unknown peripheral LO_int interrupt source\n");
603      }
604    }
605
606    /* force re-evaluation of interrupts */
607    mpc5200.pmce = PMCE_CSE_STICKY | PMCE_MSE_STICKY | PMCE_PSE_STICKY;
608
609    /* get the content of main interrupt status register */
610    pmce = mpc5200.pmce;
611  }
612
613#if (BENCHMARK_IRQ_PROCESSING == 1)
614  stop = PPC_Get_timebase_register();
615  thisTime = stop - start;
616  BSP_Total_in_ISR += thisTime;
617  if (thisTime > BSP_Worst_ISR)
618    BSP_Worst_ISR = thisTime;
619#endif
620
621  return 0;
622}
623
624/*
625 * setup irqMaskTable to support a priorized/nested interrupt environment
626 */
627static void setup_irqMaskTable( void)
628{
629  rtems_irq_prio prio = 0;
630  uint32_t i = 0,
631    j = 0,
632    mask = 0;
633
634  /* set up the priority dependent masks for peripheral interrupts */
635  for (i = BSP_PER_IRQ_LOWEST_OFFSET; i <= BSP_PER_IRQ_MAX_OFFSET; i++) {
636    prio = irqPrioTable [i];
637    mask = 0;
638
639    for (j = BSP_PER_IRQ_LOWEST_OFFSET; j <= BSP_PER_IRQ_MAX_OFFSET; j++) {
640      if (prio > irqPrioTable [j]) {
641        mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET));
642      }
643
644      if ((prio == irqPrioTable [j]) && (j >= i)) {
645        mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET));
646      }
647    }
648
649    irqMaskTable [i] = mask;
650  }
651
652  /* set up the priority dependent masks for main interrupts */
653  for (i = BSP_MAIN_IRQ_LOWEST_OFFSET; i <= BSP_MAIN_IRQ_MAX_OFFSET; i++) {
654    prio = irqPrioTable [i];
655    mask = 0;
656
657    for (j = BSP_MAIN_IRQ_LOWEST_OFFSET; j <= BSP_MAIN_IRQ_MAX_OFFSET; j++) {
658      if (prio > irqPrioTable [j]) {
659        mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET));
660      }
661
662      if ((prio == irqPrioTable [j]) && (j >= i)) {
663        mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET));
664      }
665    }
666
667    irqMaskTable [i] = mask;
668  }
669}
670
671/*
672 * Initialize MPC5x00 SIU interrupt management
673 */
674static void BSP_SIU_irq_init( void)
675{
676
677  /* disable all peripheral interrupts */
678  mpc5200.per_mask = 0xFFFFFC00;
679
680  /* peripheral interrupt priorities according to reset value */
681  mpc5200.per_pri_1 = 0xF0000000;
682  mpc5200.per_pri_2 = 0x00000000;
683  mpc5200.per_pri_3 = 0x00000000;
684
685  /* disable external interrupts IRQ0-4 / critical interrupts are routed to core_int */
686  mpc5200.ext_en_type = 0x0F000001;
687
688  /* disable main interrupts / crit. int. priorities according to reset values */
689  mpc5200.crit_pri_main_mask = 0x0001FFFF;
690
691  /* main priorities according to reset value */
692  mpc5200.main_pri_1 = 0;
693  mpc5200.main_pri_2 = 0;
694
695  /* reset all status indicators */
696  mpc5200.csa = 0x0001FFFF;
697  mpc5200.msa = 0x0001FFFF;
698  mpc5200.psa = 0x003FFFFF;
699  mpc5200.psa_be = 0x03000000;
700
701  setup_irqMaskTable();
702}
703
704rtems_status_code bsp_interrupt_facility_initialize( void)
705{
706  BSP_SIU_irq_init();
707
708  /* Install exception handler */
709  if (ppc_exc_set_handler( ASM_EXT_VECTOR, C_dispatch_irq_handler)) {
710    return RTEMS_IO_ERROR;
711  }
712  if (ppc_exc_set_handler( ASM_E300_SYSMGMT_VECTOR, C_dispatch_irq_handler)) {
713    return RTEMS_IO_ERROR;
714  }
715
716  return RTEMS_SUCCESSFUL;
717}
718
719void bsp_interrupt_handler_default( rtems_vector_number vector)
720{
721  if (vector != BSP_DECREMENTER) {
722    printk( "Spurious interrupt: 0x%08" PRIx32 "\n", vector);
723  }
724}
Note: See TracBrowser for help on using the repository browser.