source: rtems/bsps/powerpc/gen5200/irq/irq.c @ 32f5a195

Last change on this file since 32f5a195 was 32f5a195, checked in by Sebastian Huber <sebastian.huber@…>, on 06/29/21 at 12:06:03

bsps/irq: bsp_interrupt_vector_disable()

Return a status code for bsp_interrupt_vector_disable().

Update #3269.

  • Property mode set to 100644
File size: 25.0 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 */
362rtems_status_code bsp_interrupt_get_attributes(
363  rtems_vector_number         vector,
364  rtems_interrupt_attributes *attributes
365)
366{
367  return RTEMS_SUCCESSFUL;
368}
369
370rtems_status_code bsp_interrupt_is_pending(
371  rtems_vector_number vector,
372  bool               *pending
373)
374{
375  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
376  bsp_interrupt_assert(pending != NULL);
377  *pending = false;
378  return RTEMS_UNSATISFIED;
379}
380
381rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
382{
383  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
384  return RTEMS_UNSATISFIED;
385}
386
387rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
388{
389  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
390  return RTEMS_UNSATISFIED;
391}
392
393rtems_status_code bsp_interrupt_vector_is_enabled(
394  rtems_vector_number vector,
395  bool               *enabled
396)
397{
398  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
399  bsp_interrupt_assert(enabled != NULL);
400  *enabled = false;
401  return RTEMS_UNSATISFIED;
402}
403
404rtems_status_code bsp_interrupt_vector_enable( rtems_vector_number vector)
405{
406  int base_index = get_siu_irq_base_index( vector);
407
408  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
409
410  if (is_siu_irq( vector)) {
411    rtems_interrupt_level level;
412
413    rtems_interrupt_disable( level);
414
415    switch (base_index) {
416      case BSP_PER_IRQ_LOWEST_OFFSET:
417        BSP_enable_per_irq_at_siu( vector);
418        break;
419      case BSP_MAIN_IRQ_LOWEST_OFFSET:
420        BSP_enable_main_irq_at_siu( vector);
421        break;
422      case BSP_CRIT_IRQ_LOWEST_OFFSET:
423        BSP_enable_crit_irq_at_siu( vector);
424        break;
425      default:
426        bsp_interrupt_assert(0);
427        break;
428    }
429
430    rtems_interrupt_enable( level);
431  }
432
433  return RTEMS_SUCCESSFUL;
434}
435
436/*
437 * This function disables a given siu interrupt
438 */
439rtems_status_code bsp_interrupt_vector_disable( rtems_vector_number vector)
440{
441  int base_index = get_siu_irq_base_index( vector);
442
443  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
444
445  if (is_siu_irq( vector)) {
446    rtems_interrupt_level level;
447
448    rtems_interrupt_disable( level);
449
450    switch (base_index) {
451      case BSP_PER_IRQ_LOWEST_OFFSET:
452        BSP_disable_per_irq_at_siu( vector);
453        break;
454      case BSP_MAIN_IRQ_LOWEST_OFFSET:
455        BSP_disable_main_irq_at_siu( vector);
456        break;
457      case BSP_CRIT_IRQ_LOWEST_OFFSET:
458        BSP_disable_crit_irq_at_siu( vector);
459        break;
460      default:
461        bsp_interrupt_assert(0);
462        break;
463    }
464
465    rtems_interrupt_enable( level);
466  }
467
468  return RTEMS_SUCCESSFUL;
469}
470
471#if (BENCHMARK_IRQ_PROCESSING == 0)
472void BSP_IRQ_Benchmarking_Reset( void)
473{
474}
475void BSP_IRQ_Benchmarking_Report( void)
476{
477}
478#else
479#include <stdio.h>
480uint64_t BSP_Starting_TBR;
481uint64_t BSP_Total_in_ISR;
482uint32_t BSP_ISR_Count;
483uint32_t BSP_Worst_ISR;
484
485#define BSP_COUNTED_IRQ 16
486uint32_t BSP_ISR_Count_Per [BSP_COUNTED_IRQ + 1];
487
488void BSP_IRQ_Benchmarking_Reset( void)
489{
490  int i;
491
492  BSP_Starting_TBR = PPC_Get_timebase_register();
493  BSP_Total_in_ISR = 0;
494  BSP_ISR_Count = 0;
495  BSP_Worst_ISR = 0;
496  for (i = 0; i < BSP_COUNTED_IRQ; i++)
497    BSP_ISR_Count_Per [i] = 0;
498}
499
500static const char *u64tostring( char *buffer, uint64_t v)
501{
502  sprintf( buffer, "%lld cycles %lld usecs", v, (v / 33));
503  return buffer;
504}
505
506void BSP_IRQ_Benchmarking_Report( void)
507{
508  uint64_t now;
509  char buffer [96];
510  int i;
511
512  now = PPC_Get_timebase_register();
513  printk( "Started at: %s\n", u64tostring( buffer, BSP_Starting_TBR));
514  printk( "Current   : %s\n", u64tostring( buffer, now));
515  printk( "System up : %s\n", u64tostring( buffer, now - BSP_Starting_TBR));
516  printk( "ISRs      : %d\n", BSP_ISR_Count);
517  printk( "ISRs ran  : %s\n", u64tostring( buffer, BSP_Total_in_ISR));
518  printk( "Worst ISR : %s\n", u64tostring( buffer, BSP_Worst_ISR));
519  for (i = 0; i < BSP_COUNTED_IRQ; i++)
520    printk( "IRQ %d: %d\n", i, BSP_ISR_Count_Per [i]);
521  printk( "Ticks     : %d\n", Clock_driver_ticks);
522}
523#endif
524
525static void dispatch(uint32_t irq, uint32_t offset, volatile uint32_t *maskreg)
526{
527  #if (ALLOW_IRQ_NESTING == 1)
528    uint32_t msr;
529    uint32_t mask = *maskreg;
530  #endif
531
532  irq += offset;
533
534  #if (ALLOW_IRQ_NESTING == 1)
535    *maskreg = mask | irqMaskTable [irq];
536    /* Make sure that the write operation completed (cache inhibited area) */
537    *maskreg;
538    msr = ppc_external_exceptions_enable();
539  #endif
540
541  bsp_interrupt_handler_dispatch(irq);
542
543  #if (ALLOW_IRQ_NESTING == 1)
544    ppc_external_exceptions_disable(msr);
545    *maskreg = mask;
546  #endif
547}
548
549/*
550 * High level IRQ handler called from shared_raw_irq_code_entry
551 */
552static int C_dispatch_irq_handler(BSP_Exception_frame *frame, unsigned excNum)
553{
554  uint32_t irq;
555  uint32_t pmce;
556
557#if (BENCHMARK_IRQ_PROCESSING == 1)
558  uint64_t start,
559    stop,
560    thisTime;
561
562  start = PPC_Get_timebase_register();
563  BSP_ISR_Count++;
564  if (excNum < BSP_COUNTED_IRQ)
565    BSP_ISR_Count_Per [excNum]++;
566  else
567    printk( "not counting %d\n", excNum);
568#endif
569
570  /* get the content of main interrupt status register */
571  pmce = mpc5200.pmce;
572
573  /* critical interrupts are routed to the core_int, see premature
574   * initialization
575   */
576  while ((pmce & (PMCE_CSE_STICKY | PMCE_MSE_STICKY)) != 0) {
577    /* first: check for critical interrupt sources (hierarchical order)
578     * -> HI_int indicates peripheral sources
579     */
580    if ((pmce & PMCE_CSE_STICKY) != 0) {
581      /* get source of critical interrupt */
582      irq = PMCE_CSE_SOURCE(pmce);
583
584      switch (irq) {
585          /* peripheral HI_int interrupt source detected */
586        case 2:
587          /* check for valid peripheral interrupt source */
588          if ((pmce & PMCE_PSE_STICKY) != 0) {
589            /* get source of peripheral interrupt */
590            irq = PMCE_PSE_SOURCE(pmce);
591
592            dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
593          } else {
594            /* this case may not occur: no valid peripheral
595             * interrupt source */
596            printk( "No valid peripheral HI_int interrupt source\n");
597          }
598          break;
599
600          /* irq0, slice timer 1 or ccs wakeup detected */
601        case 0:
602        case 1:
603        case 3:
604
605          /* add proper offset for critical interrupts in the siu
606           * handler array */
607          irq += BSP_CRIT_IRQ_LOWEST_OFFSET;
608
609          /* Dispatch interrupt handlers */
610          bsp_interrupt_handler_dispatch( irq);
611
612          break;
613
614        default:
615          /* error: unknown interrupt source */
616          printk( "Unknown HI_int interrupt source\n");
617          break;
618      }
619    }
620
621    /* second: check for main interrupt sources (hierarchical order)
622     * -> LO_int indicates peripheral sources */
623    if ((pmce & PMCE_MSE_STICKY) != 0) {
624      /* get source of main interrupt */
625      irq = PMCE_MSE_SOURCE(pmce);
626
627      if (irq == 4) {
628          /* peripheral LO_int interrupt source detected */
629          /* check for valid peripheral interrupt source */
630          if ((pmce & PMCE_PSE_STICKY) != 0) {
631            /* get source of peripheral interrupt */
632            irq = PMCE_PSE_SOURCE(pmce);
633
634            dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
635          } else {
636            /* this case may not occur: no valid peripheral
637             * interrupt source */
638            printk( "No valid peripheral LO_int interrupt source\n");
639          }
640      } else if (irq <= 16) {
641          /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer
642           * 2 is always routed to SMI) */
643          dispatch(irq, BSP_MAIN_IRQ_LOWEST_OFFSET, &mpc5200.crit_pri_main_mask);
644      } else {
645          /* error: unknown interrupt source */
646          printk( "Unknown peripheral LO_int interrupt source\n");
647      }
648    }
649
650    /* force re-evaluation of interrupts */
651    mpc5200.pmce = PMCE_CSE_STICKY | PMCE_MSE_STICKY | PMCE_PSE_STICKY;
652
653    /* get the content of main interrupt status register */
654    pmce = mpc5200.pmce;
655  }
656
657#if (BENCHMARK_IRQ_PROCESSING == 1)
658  stop = PPC_Get_timebase_register();
659  thisTime = stop - start;
660  BSP_Total_in_ISR += thisTime;
661  if (thisTime > BSP_Worst_ISR)
662    BSP_Worst_ISR = thisTime;
663#endif
664
665  return 0;
666}
667
668/*
669 * setup irqMaskTable to support a priorized/nested interrupt environment
670 */
671static void setup_irqMaskTable( void)
672{
673  rtems_irq_prio prio = 0;
674  uint32_t i = 0,
675    j = 0,
676    mask = 0;
677
678  /* set up the priority dependent masks for peripheral interrupts */
679  for (i = BSP_PER_IRQ_LOWEST_OFFSET; i <= BSP_PER_IRQ_MAX_OFFSET; i++) {
680    prio = irqPrioTable [i];
681    mask = 0;
682
683    for (j = BSP_PER_IRQ_LOWEST_OFFSET; j <= BSP_PER_IRQ_MAX_OFFSET; j++) {
684      if (prio > irqPrioTable [j]) {
685        mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET));
686      }
687
688      if ((prio == irqPrioTable [j]) && (j >= i)) {
689        mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET));
690      }
691    }
692
693    irqMaskTable [i] = mask;
694  }
695
696  /* set up the priority dependent masks for main interrupts */
697  for (i = BSP_MAIN_IRQ_LOWEST_OFFSET; i <= BSP_MAIN_IRQ_MAX_OFFSET; i++) {
698    prio = irqPrioTable [i];
699    mask = 0;
700
701    for (j = BSP_MAIN_IRQ_LOWEST_OFFSET; j <= BSP_MAIN_IRQ_MAX_OFFSET; j++) {
702      if (prio > irqPrioTable [j]) {
703        mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET));
704      }
705
706      if ((prio == irqPrioTable [j]) && (j >= i)) {
707        mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET));
708      }
709    }
710
711    irqMaskTable [i] = mask;
712  }
713}
714
715/*
716 * Initialize MPC5x00 SIU interrupt management
717 */
718static void BSP_SIU_irq_init( void)
719{
720
721  /* disable all peripheral interrupts */
722  mpc5200.per_mask = 0xFFFFFC00;
723
724  /* peripheral interrupt priorities according to reset value */
725  mpc5200.per_pri_1 = 0xF0000000;
726  mpc5200.per_pri_2 = 0x00000000;
727  mpc5200.per_pri_3 = 0x00000000;
728
729  /* disable external interrupts IRQ0-4 / critical interrupts are routed to core_int */
730  mpc5200.ext_en_type = 0x0F000001;
731
732  /* disable main interrupts / crit. int. priorities according to reset values */
733  mpc5200.crit_pri_main_mask = 0x0001FFFF;
734
735  /* main priorities according to reset value */
736  mpc5200.main_pri_1 = 0;
737  mpc5200.main_pri_2 = 0;
738
739  /* reset all status indicators */
740  mpc5200.csa = 0x0001FFFF;
741  mpc5200.msa = 0x0001FFFF;
742  mpc5200.psa = 0x003FFFFF;
743  mpc5200.psa_be = 0x03000000;
744
745  setup_irqMaskTable();
746}
747
748rtems_status_code bsp_interrupt_facility_initialize( void)
749{
750  BSP_SIU_irq_init();
751
752  /* Install exception handler */
753  if (ppc_exc_set_handler( ASM_EXT_VECTOR, C_dispatch_irq_handler)) {
754    return RTEMS_IO_ERROR;
755  }
756  if (ppc_exc_set_handler( ASM_E300_SYSMGMT_VECTOR, C_dispatch_irq_handler)) {
757    return RTEMS_IO_ERROR;
758  }
759
760  return RTEMS_SUCCESSFUL;
761}
762
763void bsp_interrupt_handler_default( rtems_vector_number vector)
764{
765  if (vector != BSP_DECREMENTER) {
766    printk( "Spurious interrupt: 0x%08" PRIx32 "\n", vector);
767  }
768}
Note: See TracBrowser for help on using the repository browser.