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

4.104.114.95
Last change on this file since c1f289e was c1f289e, checked in by Joel Sherrill <joel.sherrill@…>, on 12/14/07 at 21:53:08

2007-12-14 Joel Sherrill <joel.sherrill@…>

  • acinclude.m4, gen5200/irq/irq.c, gen5200/startup/bspclean.c: Add mvme3100.
  • Property mode set to 100644
File size: 30.4 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 <bsp.h>
77#include <rtems.h>
78#include "../irq/irq.h"
79#include <rtems/score/apiext.h>
80#include <rtems/bspIo.h>
81#include <libcpu/raw_exception.h>
82#include "../vectors/vectors.h"
83#include "../include/mpc5200.h"
84
85
86extern uint32_t irqMaskTable[];
87
88/*
89 * default handler connected on each irq after bsp initialization
90 */
91static rtems_irq_connect_data  default_rtems_entry;
92
93/*
94 * location used to store initial tables used for interrupt
95 * management.
96 */
97static rtems_irq_global_settings*   internal_config;
98static rtems_irq_connect_data*      rtems_hdl_tbl;
99
100/*
101 * bit in the SIU mask registers (PPC bit numbering) that should
102 * be set to enable the relevant interrupt, mask of 32 is for unused entries
103 *
104 */
105const static unsigned int SIU_MaskBit[BSP_SIU_IRQ_NUMBER] =
106  {
107  0, 1, 2, 3,       /* smart_comm, psc1, psc2, psc3            */
108  4, 5, 6, 7,       /* irda/psc6, eth, usb, ata                */
109  8, 9, 10, 11,     /* pci_ctrl, pci_sc_rx, pci_sc_tx, psc4    */
110  12, 13, 14, 15,   /* psc5,spi_modf, spi_spif, i2c1           */
111  16, 17, 18, 19,   /* i2c, can1, can2, ir_rx                  */
112  20, 21, 15, 16,   /* ir_rx, xlb_arb, slice_tim2, irq1,       */
113  17, 18, 19, 20,   /* irq2, irq3, lo_int, rtc_pint            */
114  21, 22, 23, 24,   /* rtc_sint, gpio_std, gpio_wkup, tmr0     */
115  25, 26, 27, 28,   /* tmr1, tmr2, tmr3, tmr4                  */
116  29, 30, 31, 32,   /* tmr5, tmr6, tmr7, res                   */
117  32, 32, 32        /* res, res, res                           */
118  };
119
120/*
121 * Check if symbolic IRQ name is a Processor IRQ
122 */
123static inline int is_processor_irq(const rtems_irq_symbolic_name irqLine)
124{
125
126  return (((int)irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) &
127          ((int)irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET));
128}
129
130/*
131 * Check for SIU IRQ and return base index
132 */
133static inline int is_siu_irq(const rtems_irq_symbolic_name irqLine)
134{
135
136  return (((int)irqLine <= BSP_SIU_IRQ_MAX_OFFSET) &&
137           ((int)irqLine >= BSP_SIU_IRQ_LOWEST_OFFSET));
138
139}
140
141
142/*
143 * Check for SIU IRQ and return base index
144 */
145static inline int get_siu_irq_base_index(const rtems_irq_symbolic_name irqLine)
146{
147
148  if (irqLine <= BSP_PER_IRQ_MAX_OFFSET)
149    return BSP_PER_IRQ_LOWEST_OFFSET;
150
151  if (irqLine <= BSP_MAIN_IRQ_MAX_OFFSET)
152    return BSP_MAIN_IRQ_LOWEST_OFFSET;
153  if (irqLine <= BSP_CRIT_IRQ_MAX_OFFSET)
154    return BSP_CRIT_IRQ_LOWEST_OFFSET;
155
156  return -1;
157}
158
159
160static inline void BSP_enable_per_irq_at_siu(
161  const rtems_irq_symbolic_name irqLine
162)
163{
164  uint8_t lo_hi_ind = 0, prio_index_offset;
165  uint32_t *reg;
166  rtems_irq_prio *irqPrioTable = internal_config->irqPrioTbl;
167  volatile uint32_t per_pri_1,main_pri_1, crit_pri_main_mask, per_mask;
168
169  /* calculate the index offset of priority value bit field */
170  prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
171
172  /* set interrupt priorities */
173  if (irqPrioTable[irqLine] <= 15) {
174
175    /* set peripheral int priority */
176    reg = (uint32_t *)(&(mpc5200.per_pri_1));
177
178    /* choose proper register */
179    reg += (irqLine >> 3);
180
181    /* set priority as given in priority table */
182    *reg |= (irqPrioTable[irqLine] << (28 - (prio_index_offset<< 2)));
183
184    /* test msb (hash-bit) and set LO_/HI_int indicator */
185    if ((lo_hi_ind = (irqPrioTable[irqLine] >> 3))) {
186
187      /* set critical HI_int priority */
188      reg = (uint32_t *)(&(mpc5200.crit_pri_main_mask));
189      *reg |= (irqPrioTable[BSP_SIU_IRQ_HI_INT] << 26);
190
191      /*
192       * critical interrupt handling for the 603le core is not
193       * yet supported, routing of critical interrupts is forced
194       * to core_int (bit 31 / CEb)
195       */
196       mpc5200.ext_en_type |= 1;
197
198    } else {
199      if (irqPrioTable[irqLine] <= 15) {
200        /* set main LO_int priority */
201        reg = (uint32_t *)(&(mpc5200.main_pri_1));
202        *reg |= (irqPrioTable[BSP_SIU_IRQ_LO_INT] << 16);
203      }
204    }
205  }
206
207  /* if LO_int ind., enable (unmask) main interrupt */
208  if (!lo_hi_ind) {
209    mpc5200.crit_pri_main_mask &=
210      ~(0x80000000 >> SIU_MaskBit[BSP_SIU_IRQ_LO_INT]);
211  }
212
213
214  /* enable (unmask) peripheral interrupt */
215  mpc5200.per_mask &= ~(0x80000000 >> SIU_MaskBit[irqLine]);
216
217  main_pri_1         = mpc5200.main_pri_1;
218  crit_pri_main_mask = mpc5200.crit_pri_main_mask;
219  per_pri_1          = mpc5200.per_pri_1;
220  per_mask           = mpc5200.per_mask;
221
222
223}
224
225
226static inline void BSP_enable_main_irq_at_siu(
227  const rtems_irq_symbolic_name irqLine
228)
229{
230
231  uint8_t prio_index_offset;
232  uint32_t *reg;
233  rtems_irq_prio *irqPrioTable = internal_config->irqPrioTbl;
234
235  /* calculate the index offset of priority value bit field */
236  prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
237
238  /* set main interrupt priority */
239  if (irqPrioTable[irqLine] <= 15) {
240
241    /* set main int priority */
242    reg = (uint32_t *)(&(mpc5200.main_pri_1));
243
244    /* choose proper register */
245    reg += (irqLine >> 3);
246
247    /* set priority as given in priority table */
248    *reg |= (irqPrioTable[irqLine] << (28 - (prio_index_offset << 2)));
249
250    if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
251      /* enable external irq-pin */
252      mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
253    }
254  }
255
256  /* enable (unmask) main interrupt */
257  mpc5200.crit_pri_main_mask &= ~(0x80000000 >> SIU_MaskBit[irqLine]);
258
259}
260
261
262static inline void BSP_enable_crit_irq_at_siu(
263  const rtems_irq_symbolic_name irqLine
264)
265{
266  uint8_t prio_index_offset;
267  uint32_t *reg;
268  rtems_irq_prio *irqPrioTable = internal_config->irqPrioTbl;
269
270  prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
271
272  /*
273   * critical interrupt handling for the 603Le core is not
274   * yet supported, routing of critical interrupts is forced
275   * to core_int (bit 31 / CEb)
276   */
277  mpc5200.ext_en_type |= 1;
278
279
280  /* set critical interrupt priorities */
281  if (irqPrioTable[irqLine] <= 3) {
282
283    /* choose proper register */
284    reg = (uint32_t *)(&(mpc5200.crit_pri_main_mask));
285
286    /* set priority as given in priority table */
287    *reg |= (irqPrioTable[irqLine] << (30 - (prio_index_offset << 1)));
288
289    /* external irq0-pin */
290    if (irqLine == BSP_SIU_IRQ_IRQ1) {
291      /* enable external irq-pin */
292      mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
293    }
294  }
295}
296
297
298static inline void BSP_disable_per_irq_at_siu(
299  const rtems_irq_symbolic_name 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
317
318static inline void BSP_disable_main_irq_at_siu(
319  const rtems_irq_symbolic_name irqLine
320)
321{
322  uint8_t prio_index_offset;
323  uint32_t *reg;
324
325  /* calculate the index offset of priority value bit field */
326  prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
327
328  /* disable (mask) main interrupt */
329  mpc5200.crit_pri_main_mask |= (0x80000000 >> SIU_MaskBit[irqLine]);
330
331  if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
332    /* disable external irq-pin */
333    mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
334  }
335
336  /* reset priority to lowest level (reset value) */
337  reg = (uint32_t *)(&(mpc5200.main_pri_1));
338  reg  += (irqLine >> 3);
339  *reg &= ~(15 << (28 - (prio_index_offset << 2)));
340}
341
342
343static inline void BSP_disable_crit_irq_at_siu(
344  const rtems_irq_symbolic_name irqLine
345)
346{
347  uint8_t prio_index_offset;
348  uint32_t *reg;
349
350  prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
351
352  /* reset critical int priority to lowest level (reset value) */
353  reg = (uint32_t *)(&(mpc5200.crit_pri_main_mask));
354  *reg &= ~(3 << (30 - (prio_index_offset << 1)));
355
356  if (irqLine == BSP_SIU_IRQ_IRQ1) {
357    /* disable external irq0-pin */
358    mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
359  }
360}
361
362
363/*
364 * ------------------------ RTEMS Irq helper functions ----------------
365 */
366
367
368/*
369 * This function check that the value given for the irq line
370 * is valid.
371 */
372static int isValidInterrupt(int irq)
373{
374  if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET) )
375    return 0;
376  return 1;
377}
378
379
380 /*
381  * This function enables a given siu interrupt
382  */
383int BSP_irq_enable_at_siu(const rtems_irq_symbolic_name irqLine)
384{
385  int base_index;
386
387  if (is_siu_irq(irqLine)) {
388    if ((base_index = get_siu_irq_base_index(irqLine)) != -1) {
389
390      switch(base_index) {
391        case BSP_PER_IRQ_LOWEST_OFFSET:
392          BSP_enable_per_irq_at_siu(irqLine);
393          break;
394        case BSP_MAIN_IRQ_LOWEST_OFFSET:
395          BSP_enable_main_irq_at_siu(irqLine);
396          break;
397        case BSP_CRIT_IRQ_LOWEST_OFFSET:
398          BSP_enable_crit_irq_at_siu(irqLine);
399          break;
400        default:
401          printk("No valid base index\n");
402          break;
403      }
404    }
405  }
406  return 0;
407}
408
409/*
410 * This function disables a given siu interrupt
411 */
412int BSP_irq_disable_at_siu(const rtems_irq_symbolic_name irqLine)
413{
414  int base_index;
415
416  if ( (base_index = get_siu_irq_base_index(irqLine)) == -1)
417    return 1;
418
419  switch(base_index) {
420    case BSP_PER_IRQ_LOWEST_OFFSET:
421      BSP_disable_per_irq_at_siu(irqLine);
422      break;
423    case BSP_MAIN_IRQ_LOWEST_OFFSET:
424      BSP_disable_main_irq_at_siu(irqLine);
425      break;
426    case BSP_CRIT_IRQ_LOWEST_OFFSET:
427      BSP_disable_crit_irq_at_siu(irqLine);
428      break;
429    default:
430      printk("No valid base index\n");
431      break;
432  }
433  return 0;
434}
435
436
437/*
438 * --------------------- RTEMS Single Irq Handler Mngt Routines -------------
439 */
440
441 /*
442  * This function removes the default entry and installs a device
443  * interrupt handler
444  */
445int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
446{
447  rtems_interrupt_level level;
448
449  if (!isValidInterrupt(irq->name)) {
450    printk("not a valid interrupt\n");
451    return 0;
452  }
453
454  /*
455   * Check if default handler is actually connected. If not issue an error.
456   * RATIONALE : to always have the same transition by forcing the user
457   * to get the previous handler before accepting to disconnect.
458   */
459  if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
460    printk( "Default handler not there\n" );
461    return 0;
462  }
463
464  rtems_interrupt_disable(level);
465
466  /*
467   * store the data provided by user
468   */
469  rtems_hdl_tbl[irq->name] = *irq;
470
471  if (is_siu_irq(irq->name)) {
472    /*
473     * Enable interrupt at siu level
474     */
475    BSP_irq_enable_at_siu(irq->name);
476  } else {
477    if (is_processor_irq(irq->name)) {
478      /*
479       * Should Enable exception at processor level but not needed.
480       * Will restore EE flags at the end of the routine anyway.
481       */
482    } else {
483      printk("not a valid interrupt\n");
484      return 0;
485    }
486  }
487
488  /*
489   * Enable interrupt on device
490   */
491  if (irq->on)
492    irq->on(irq);
493
494  rtems_interrupt_enable(level);
495  return 1;
496}
497
498
499 /*
500  * This function procures the current interrupt handler
501  */
502int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq)
503{
504  if (!isValidInterrupt(irq->name)) {
505    return 0;
506  }
507  *irq = rtems_hdl_tbl[irq->name];
508  return 1;
509}
510
511
512 /*
513  * This function removes a device interrupt handler and restores
514  * the default entry
515  */
516int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
517{
518  rtems_interrupt_level level;
519
520  if (!isValidInterrupt(irq->name)) {
521    return 0;
522  }
523
524  /*
525   * Check if default handler is actually connected. If not issue an error.
526   * RATIONALE : to always have the same transition by forcing the user
527   * to get the previous handler before accepting to disconnect.
528   */
529  if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
530    return 0;
531  }
532
533  rtems_interrupt_disable(level);
534
535  if (is_siu_irq(irq->name)) {
536    /*
537     * disable interrupt at PIC level
538     */
539    BSP_irq_disable_at_siu(irq->name);
540  }
541
542  if (is_processor_irq(irq->name)) {
543    /*
544     * disable exception at processor level
545     */
546  }
547
548  /*
549   * Disable interrupt on device
550   */
551  if (irq->off)
552    irq->off(irq);
553
554  /*
555   * restore the default irq value
556   */
557  rtems_hdl_tbl[irq->name] = default_rtems_entry;
558
559  rtems_interrupt_enable(level);
560
561  return 1;
562}
563
564
565/*
566 * --------------------- RTEMS Global Irq Handler Mngt Routines -------------
567 */
568
569/*
570 * This function set up interrupt management dependent on the
571 * given configuration
572 */
573int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
574{
575  int                   i;
576  rtems_interrupt_level level;
577
578  /*
579   * Store various code accelerators
580   */
581  internal_config   = config;
582  default_rtems_entry   = config->defaultEntry;
583  rtems_hdl_tbl   = config->irqHdlTbl;
584
585  rtems_interrupt_disable(level);
586
587  /*
588   * start with SIU IRQs
589   */
590  for (i=BSP_SIU_IRQ_LOWEST_OFFSET;
591       i < BSP_SIU_IRQ_LOWEST_OFFSET + BSP_SIU_IRQ_NUMBER ;
592       i++) {
593
594    if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
595      BSP_irq_enable_at_siu(i);
596      if (rtems_hdl_tbl[i].on)
597        rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
598
599    } else {
600      if (rtems_hdl_tbl[i].off)
601        rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
602      BSP_irq_disable_at_siu(i);
603    }
604  }
605
606  /*
607   * finish with Processor exceptions handled like IRQs
608   */
609  for (i=BSP_PROCESSOR_IRQ_LOWEST_OFFSET;
610       i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER;
611       i++) {
612
613    if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
614      if (rtems_hdl_tbl[i].on)
615        rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
616
617    } else {
618      if (rtems_hdl_tbl[i].off)
619        rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
620    }
621  }
622
623  rtems_interrupt_enable(level);
624  return 1;
625}
626
627
628int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
629{
630  *config = internal_config;
631  return 0;
632}
633
634#include <stdio.h>
635uint64_t BSP_Starting_TBR;
636uint64_t BSP_Total_in_ISR;
637uint32_t BSP_ISR_Count;
638uint32_t BSP_Worst_ISR;
639#define BSP_COUNTED_IRQ 16
640uint32_t BSP_ISR_Count_Per[BSP_COUNTED_IRQ + 1];
641
642void BSP_initialize_IRQ_Timing(void)
643{
644  int i;
645  BSP_Starting_TBR = PPC_Get_timebase_register();
646  BSP_Total_in_ISR = 0;
647  BSP_ISR_Count = 0;
648  BSP_Worst_ISR = 0;
649  for ( i=0 ; i<BSP_COUNTED_IRQ ; i++ )
650    BSP_ISR_Count_Per[i] = 0;
651}
652
653static const char * u64tostring(
654  char *buffer,
655  uint64_t v
656)
657{
658  sprintf( buffer, "%lld %lld usecs", v, (v / 33) );
659  return buffer;
660}
661void BSP_report_IRQ_Timing(void)
662{
663  uint64_t now;
664  char buffer[96];
665  int i;
666
667  now = PPC_Get_timebase_register();
668  printk( "Started at: %s\n", u64tostring(buffer, BSP_Starting_TBR) );
669  printk( "Current   : %s\n", u64tostring(buffer, now) );
670  printk( "System up : %s\n", u64tostring(buffer, now - BSP_Starting_TBR) );
671  printk( "ISRs      : %d\n", BSP_ISR_Count );
672  printk( "ISRs ran  : %s\n", u64tostring(buffer, BSP_Total_in_ISR) );
673  printk( "Worst ISR : %s\n", u64tostring(buffer, BSP_Worst_ISR) );
674  for ( i=0 ; i<BSP_COUNTED_IRQ ; i++ )
675    printk( "IRQ %d: %d\n", i, BSP_ISR_Count_Per[i] );
676  printk( "Ticks     : %d\n",  Clock_driver_ticks );
677}
678
679/*
680 * High level IRQ handler called from shared_raw_irq_code_entry
681 */
682int C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum)
683{
684  register unsigned int irq;
685  register unsigned int msr;
686  register unsigned int new_msr;
687  register unsigned int pmce;
688  register unsigned int crit_pri_main_mask, per_mask;
689  uint64_t start, stop, thisTime;
690
691  start = PPC_Get_timebase_register();
692  BSP_ISR_Count++;
693  if ( excNum < BSP_COUNTED_IRQ )
694    BSP_ISR_Count_Per[excNum]++;
695  else
696    printk( "not counting %d\n", excNum);
697
698  switch (excNum) {
699    /*
700     * Handle decrementer interrupt
701     */
702    case ASM_DEC_VECTOR:
703
704      /* call the module specific handler and pass the specific handler */
705      rtems_hdl_tbl[BSP_DECREMENTER].hdl(0);
706
707      return 0;
708
709    case ASM_60X_SYSMGMT_VECTOR:
710
711      /* get the content of main interrupt status register */
712      pmce =  mpc5200.pmce;
713
714      /* main interrupts may be routed to SMI, see bit SMI/INT select
715       * bit in main int. priorities
716       */
717      while (CHK_MSE_STICKY(pmce)) {
718
719        /* check for main interrupt sources (hirarchical order)
720         * -> LO_int indicates peripheral sources
721         */
722        if (CHK_MSE_STICKY(pmce)) {
723          /* get source of main interrupt */
724          irq = MSE_SOURCE(pmce);
725          switch(irq) {
726
727            /* irq1-3, RTC, GPIO, TMR0-7 detected (attention:
728             * slice timer 2 is always routed to SMI)
729             */
730            case 0: /* slice timer 2 */
731            case 1:
732            case 2:
733            case 3:
734            case 5:
735            case 6:
736            case 7:
737            case 8:
738            case 9:
739            case 10:
740            case 11:
741            case 12:
742            case 13:
743            case 14:
744            case 15:
745            case 16:
746
747              /* add proper offset for main interrupts in
748               * the siu handler array
749               */
750              irq += BSP_MAIN_IRQ_LOWEST_OFFSET;
751
752              /* save original mask and disable all lower
753               * priorized main interrupts
754               */
755              crit_pri_main_mask =  mpc5200.crit_pri_main_mask;
756              mpc5200.crit_pri_main_mask |= irqMaskTable[irq];
757
758              /* enable interrupt nesting */
759              _CPU_MSR_GET(msr);
760              new_msr = msr | MSR_EE;
761              _CPU_MSR_SET(new_msr);
762
763              /* call the module specific handler and pass the
764               * specific handler
765               */
766              rtems_hdl_tbl[irq].hdl(0);
767
768              /* disable interrupt nesting */
769              _CPU_MSR_SET(msr);
770
771              /* restore original interrupt mask */
772              mpc5200.crit_pri_main_mask = crit_pri_main_mask;
773
774              break;
775
776            /* peripheral LO_int interrupt source detected */
777            case 4:
778
779              /* check for valid peripheral interrupt source */
780              if (CHK_PSE_STICKY(pmce)) {
781                /* get source of peripheral interrupt */
782                irq = PSE_SOURCE(pmce);
783
784                /* add proper offset for peripheral interrupts
785                 * in the siu handler array
786                 */
787                irq += BSP_PER_IRQ_LOWEST_OFFSET;
788
789                /* save original mask and disable all lower
790                 * priorized main interrupts
791                 */
792                per_mask =  mpc5200.per_mask;
793                mpc5200.per_mask |= irqMaskTable[irq];
794
795                /* enable interrupt nesting */
796                _CPU_MSR_GET(msr);
797                new_msr = msr | MSR_EE;
798                _CPU_MSR_SET(new_msr);
799
800                /* call the module specific handler and pass
801                 * the specific handler
802                 */
803                rtems_hdl_tbl[irq].hdl(0);
804
805                /* disable interrupt nesting */
806                _CPU_MSR_SET(msr);
807
808                /* restore original interrupt mask */
809                mpc5200.per_mask = per_mask;
810
811                /* force re-evaluation of peripheral interrupts */
812                CLR_PSE_STICKY(mpc5200.pmce);
813              } else {
814                /* this case may not occur: no valid peripheral
815                 * interrupt source
816                 */
817                printk("No valid peripheral LO_int interrupt source\n");
818              }
819              break;
820              /* error: unknown interrupt source */
821            default:
822              printk("Unknown peripheral LO_int interrupt source\n");
823              break;
824          }
825
826          /* force re-evaluation of main interrupts */
827          CLR_MSE_STICKY(mpc5200.pmce);
828        }
829
830        /* get the content of main interrupt status register */
831        pmce =  mpc5200.pmce;
832      }
833      break;
834
835    case ASM_EXT_VECTOR:
836      /* get the content of main interrupt status register */
837      pmce =  mpc5200.pmce;
838
839      /* critical interrupts may be routed to the core_int
840       * dependent on premature initialization, see bit 31 (CEbsH)
841       */
842      while((CHK_CE_SHADOW(pmce) && CHK_CSE_STICKY(pmce)) ||
843             CHK_MSE_STICKY(pmce) || CHK_PSE_STICKY(pmce) ) {
844
845        /* first: check for critical interrupt sources (hierarchical order)
846         * -> HI_int indicates peripheral sources
847         */
848        if (CHK_CE_SHADOW(pmce) && CHK_CSE_STICKY(pmce)) {
849          /* get source of critical interrupt */
850          irq = CSE_SOURCE(pmce);
851          switch(irq) {
852            /* irq0, slice timer 1 or ccs wakeup detected */
853            case 0:
854            case 1:
855            case 3:
856
857              /* add proper offset for critical interrupts in the siu
858               * handler array */
859              irq += BSP_CRIT_IRQ_LOWEST_OFFSET;
860
861              /* call the module specific handler and pass the
862               * specific handler */
863              rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
864              break;
865
866            /* peripheral HI_int interrupt source detected */
867            case 2:
868              /* check for valid peripheral interrupt source */
869              if (CHK_PSE_STICKY(pmce)) {
870                /* get source of peripheral interrupt */
871                irq = PSE_SOURCE(pmce);
872
873                /* add proper offset for peripheral interrupts in the
874                 * siu handler array */
875                irq += BSP_PER_IRQ_LOWEST_OFFSET;
876
877                /* save original mask and disable all lower
878                 * priorized main interrupts */
879                per_mask =  mpc5200.per_mask;
880                mpc5200.per_mask |= irqMaskTable[irq];
881
882                /* enable interrupt nesting */
883                _CPU_MSR_GET(msr);
884                new_msr = msr | MSR_EE;
885                _CPU_MSR_SET(new_msr);
886
887                /* call the module specific handler and pass the
888                 * specific handler */
889                rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
890
891                _CPU_MSR_SET(msr);
892
893                /* restore original interrupt mask */
894                mpc5200.per_mask = per_mask;
895
896                /* force re-evaluation of peripheral interrupts */
897                CLR_PSE_STICKY(mpc5200.pmce);
898              } else {
899                /* this case may not occur: no valid peripheral
900                 * interrupt source */
901                printk("No valid peripheral HI_int interrupt source\n");
902              }
903              break;
904            default:
905              /* error: unknown interrupt source */
906              printk("Unknown HI_int interrupt source\n");
907              break;
908          }
909          /* force re-evaluation of critical interrupts */
910          CLR_CSE_STICKY(mpc5200.pmce);
911        }
912
913        /* second: check for main interrupt sources (hierarchical order)
914         * -> LO_int indicates peripheral sources */
915        if (CHK_MSE_STICKY(pmce)) {
916          /* get source of main interrupt */
917          irq = MSE_SOURCE(pmce);
918
919          switch (irq) {
920
921            /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer
922             * 2 is always routed to SMI) */
923            case 1:
924            case 2:
925            case 3:
926            case 5:
927            case 6:
928            case 7:
929            case 8:
930            case 9:
931            case 10:
932            case 11:
933            case 12:
934            case 13:
935            case 14:
936            case 15:
937            case 16:
938              /* add proper offset for main interrupts in the siu
939               * handler array */
940              irq += BSP_MAIN_IRQ_LOWEST_OFFSET;
941
942              /* save original mask and disable all lower priorized
943               * main interrupts*/
944              crit_pri_main_mask =  mpc5200.crit_pri_main_mask;
945              mpc5200.crit_pri_main_mask |= irqMaskTable[irq];
946
947              /* enable interrupt nesting */
948              _CPU_MSR_GET(msr);
949              new_msr = msr | MSR_EE;
950              _CPU_MSR_SET(new_msr);
951
952              /* call the module specific handler and pass the specific
953               * handler */
954              rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
955
956              /* disable interrupt nesting */
957              _CPU_MSR_SET(msr);
958
959              /* restore original interrupt mask */
960              mpc5200.crit_pri_main_mask = crit_pri_main_mask;
961              break;
962
963          /* peripheral LO_int interrupt source detected */
964            case 4:
965              /* check for valid peripheral interrupt source */
966              if (CHK_PSE_STICKY(pmce)) {
967                /* get source of peripheral interrupt */
968                irq = PSE_SOURCE(pmce);
969
970                /* add proper offset for peripheral interrupts in the siu
971                 * handler array */
972                irq += BSP_PER_IRQ_LOWEST_OFFSET;
973
974                /* save original mask and disable all lower priorized main
975                 * interrupts */
976                per_mask =  mpc5200.per_mask;
977                mpc5200.per_mask |= irqMaskTable[irq];
978
979                /* enable interrupt nesting */
980                _CPU_MSR_GET(msr);
981                new_msr = msr | MSR_EE;
982                _CPU_MSR_SET(new_msr);
983
984                /* call the module specific handler and pass the
985                 * specific handler */
986                rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
987
988                /* disable interrupt nesting */
989                _CPU_MSR_SET(msr);
990
991                /* restore original interrupt mask */
992                mpc5200.per_mask = per_mask;
993
994                /* force re-evaluation of peripheral interrupts */
995                CLR_PSE_STICKY(mpc5200.pmce);
996              } else {
997                /* this case may not occur: no valid peripheral
998                 * interrupt source */
999                printk("No valid peripheral LO_int interrupt source\n");
1000              }
1001              break;
1002
1003            /* error: unknown interrupt source */
1004            default:
1005              printk("Unknown peripheral LO_int interrupt source\n");
1006              break;
1007          }
1008          /* force re-evaluation of main interrupts */
1009          CLR_MSE_STICKY(mpc5200.pmce);
1010        }
1011        /* get the content of main interrupt status register */
1012        pmce =  mpc5200.pmce;
1013      }
1014      break;
1015
1016    default:
1017      printk("Unknown processor exception\n");
1018      break;
1019
1020  } /* end of switch(excNum) */
1021  return 0;
1022}
1023
1024
1025void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
1026{
1027  /*
1028   * Process pending signals that have not already been
1029   * processed by _Thread_Displatch. This happens quite
1030   * unfrequently : the ISR must have posted an action
1031   * to the current running thread.
1032   */
1033  if ( _Thread_Do_post_task_switch_extension ||
1034       _Thread_Executing->do_post_task_switch_extension )
1035    {
1036
1037    _Thread_Executing->do_post_task_switch_extension = FALSE;
1038    _API_extensions_Run_postswitch();
1039
1040    }
1041  /*
1042   * I plan to process other thread related events here.
1043   * This will include DEBUG session requested from keyboard...
1044   */
1045}
Note: See TracBrowser for help on using the repository browser.