source: rtems/c/src/lib/libbsp/powerpc/mvme5500/irq/irq.c @ 0296f518

4.104.114.95
Last change on this file since 0296f518 was 0296f518, checked in by Till Straumann <strauman@…>, on 12/12/07 at 01:16:34

2007-12-11 Till Straumann <strauman@…>

  • Makefile.am, irq/irq.c, irq/irq.h, irq/irq_init.c: use new exception/irq support from libcpu/powerpc/new-exceptions/bspsupport rather than borrowing from ../shared/vectors ../shared/irq
  • Property mode set to 100644
File size: 14.6 KB
Line 
1/*  irq.c
2 *
3 *  This file contains the implementation of the function described in irq.h
4 *
5 *  Copyright (C) 1998, 1999 valette@crf.canon.fr
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.OARcorp.com/rtems/license.html.
10 *
11 *  Acknowledgement May 2004 : to Till Straumann <strauman@slac.stanford.edu>
12 *  for some inputs.
13 *
14 *  Copyright 2003, 2004, 2005, 2007  Shuchen Kate Feng <feng1@bnl.gov>,
15 *                  NSLS,Brookhaven National Laboratory
16 *  1) Modified and added support for the MVME5500 board.
17 *  2) The implementation of picIsrTable[] is an original work by the
18 *     author to optimize the software IRQ priority scheduling because
19 *     Discovery controller does not provide H/W IRQ priority schedule.
20 *     It ensures the fastest/faster interrupt service to the
21 *     highest/higher priority IRQ, if pendig.
22 *  3) _CPU_MSR_SET() needs RTEMS_COMPILER_MEMORY_BARRIER()
23 *
24 */
25 
26#include <rtems/system.h>
27#include <bsp.h>
28#include <bsp/irq.h>
29#include <rtems/score/thread.h>
30#include <rtems/score/apiext.h>
31#include <libcpu/raw_exception.h>
32#include <rtems/rtems/intr.h>
33#include <libcpu/io.h>
34#include <libcpu/byteorder.h>
35#include <bsp/vectors.h>
36
37#include <rtems/bspIo.h> /* for printk */
38#include "bsp/gtreg.h"
39
40#define HI_INT_CAUSE 0x40000000
41
42#define MAX_IRQ_LOOP 30
43
44#define EDGE_TRIGGER
45
46/* #define DEBUG_IRQ*/
47
48/*
49 * pointer to the mask representing the additionnal irq vectors
50 * that must be disabled when a particular entry is activated.
51 * They will be dynamically computed from the table given
52 * in BSP_rtems_irq_mngt_set();
53 * CAUTION : this table is accessed directly by interrupt routine
54 *           prologue.
55 */
56static unsigned int BSP_irq_prio_mask_tbl[3][BSP_PIC_IRQ_NUMBER];
57
58/*
59 * location used to store initial tables used for interrupt
60 * management.
61 */
62static rtems_irq_global_settings*       internal_config;
63/* handler table (cached copy ) */
64static rtems_irq_connect_data*          rtems_hdl_tbl;
65/*
66 * default handler connected on each irq after bsp initialization
67 * (locally cached copy)
68 */
69void (*default_rtems_hdl)(rtems_irq_hdl_param) = (void(*)(rtems_irq_hdl_param)) -1;
70
71
72static volatile unsigned  *BSP_irqMask_reg[3];
73static volatile unsigned  *BSP_irqCause_reg[3];
74static volatile unsigned  BSP_irqMask_cache[3]={0,0,0};
75
76
77static int picIsrTblPtr=0;
78static unsigned int GPPIrqInTbl=0;
79static unsigned long long MainIrqInTbl=0;
80
81/*
82 * The software developers are forbidden to setup picIsrTable[],
83 * as it is a powerful engine for the BSP to find the pending
84 * highest priority IRQ at run time.  It ensures the fastest/faster
85 * interrupt service to the highest/higher priority IRQ, if pendig.
86 *
87 * The picIsrTable[96] is updated dynamically at run time
88 * based on the priority levels set at BSPirqPrioTable[96],
89 * while the BSP_enable_pic_irq(), and BSP_disable_pic_irq()
90 * commands are invoked.
91 *
92 * The picIsrTable[96] lists the enabled CPU main and GPP external interrupt
93 * numbers [0 (lowest)- 95 (highest)] starting from the highest priority
94 * one to the lowest priority one. The highest priority interrupt is
95 * located at picIsrTable[0], and the lowest priority interrupt is located
96 * at picIsrTable[picIsrTblPtr-1].
97 *
98 *
99 */
100/* BitNums for Main Interrupt Lo/High Cause and GPP, -1 means invalid bit */
101static unsigned int picIsrTable[BSP_PIC_IRQ_NUMBER]={ 
102     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
103     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
104     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
105     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
106     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
107     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
108     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
109     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
110     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
111     -1, -1, -1, -1, -1, -1 };
112
113
114/*
115 * Check if IRQ is a MAIN CPU internal IRQ or GPP external IRQ
116 */
117static inline int is_pic_irq(const rtems_irq_number irqLine)
118{
119  return (((int) irqLine <= BSP_GPP_IRQ_MAX_OFFSET) &
120          ((int) irqLine >= BSP_MICL_IRQ_LOWEST_OFFSET)
121         );
122}
123
124/*
125 * Check if IRQ is a Porcessor IRQ
126 */
127static inline int is_processor_irq(const rtems_irq_number irqLine)
128{
129  return (((int) irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) &
130          ((int) irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET)
131         );
132}
133
134static inline unsigned int divIrq32(unsigned irq)
135{
136  return(irq/32);
137}
138
139static inline unsigned int modIrq32(unsigned irq)
140{
141   return(irq%32);
142}
143
144/*
145 * ------------------------ RTEMS Irq helper functions ----------------
146 */
147 
148/*
149 * Caution : this function assumes the variable "internal_config"
150 * is already set and that the tables it contains are still valid
151 * and accessible.
152 */
153static void compute_pic_masks_from_prio(rtems_irq_global_settings *config)
154{
155  int i,j, k;
156  unsigned long long irq_prio_mask=0;
157
158  /*
159   * Always mask at least current interrupt to prevent re-entrance
160   */
161  for (i=0; i <BSP_PIC_IRQ_NUMBER; i++) {
162    switch(i) {
163      case BSP_MAIN_GPP7_0_IRQ:
164      case BSP_MAIN_GPP15_8_IRQ:
165      case BSP_MAIN_GPP23_16_IRQ:
166      case BSP_MAIN_GPP31_24_IRQ:
167        for (k=0; k< 3; k++)
168            BSP_irq_prio_mask_tbl[k][i]=0;
169
170        irq_prio_mask =0;
171        break;
172      default :
173        irq_prio_mask = (unsigned long long) (1LLU << i);
174        break;
175    }
176   
177    if (irq_prio_mask) {
178    for (j = 0; j <BSP_MAIN_IRQ_NUMBER; j++) {
179        /*
180         * Mask interrupts at PIC level that have a lower priority
181         * or <Till Straumann> a equal priority.
182         */
183        if (config->irqPrioTbl [i] >= config->irqPrioTbl [j])
184           irq_prio_mask |= (unsigned long long)(1LLU << j);
185    }
186   
187
188    BSP_irq_prio_mask_tbl[0][i] = irq_prio_mask & 0xffffffff;
189    BSP_irq_prio_mask_tbl[1][i] = (irq_prio_mask>>32) & 0xffffffff;
190#ifdef DEBUG
191    printk("irq_mask_prio_tbl[%d]:0x%8x%8x\n",i,BSP_irq_prio_mask_tbl[1][i],
192           BSP_irq_prio_mask_tbl[0][i]);
193#endif
194
195    BSP_irq_prio_mask_tbl[2][i] = 1<<i;
196    /* Compute for the GPP priority interrupt mask */
197    for (j=BSP_GPP_IRQ_LOWEST_OFFSET; j <BSP_PROCESSOR_IRQ_LOWEST_OFFSET; j++) {     
198      if (config->irqPrioTbl [i] >= config->irqPrioTbl [j])
199           BSP_irq_prio_mask_tbl[2][i] |= 1 << (j-BSP_GPP_IRQ_LOWEST_OFFSET);
200    }
201    }
202  }
203}
204
205
206static void UpdateMainIrqTbl(int irqNum)
207{
208  int i=0, j, shifted=0;
209
210  switch (irqNum) {
211    case BSP_MAIN_GPP7_0_IRQ:
212    case BSP_MAIN_GPP15_8_IRQ:
213    case BSP_MAIN_GPP23_16_IRQ:
214    case BSP_MAIN_GPP31_24_IRQ: 
215      return;  /* Do nothing, let GPP take care of it */
216      break;
217  }
218#ifdef SHOW_MORE_INIT_SETTINGS
219  unsigned long val2, val1;
220#endif
221
222  /* If entry not in table*/
223  if ( ((irqNum<BSP_GPP_IRQ_LOWEST_OFFSET) &&
224        (!((unsigned long long)(1LLU << irqNum) & MainIrqInTbl))) ||
225       ((irqNum>BSP_MICH_IRQ_MAX_OFFSET) &&
226        (!(( 1 << (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)) & GPPIrqInTbl))))
227  {
228      while ( picIsrTable[i]!=-1) {
229        if (internal_config->irqPrioTbl[irqNum]>internal_config->irqPrioTbl[picIsrTable[i]]) {
230          /* all other lower priority entries shifted right */
231          for (j=picIsrTblPtr;j>i; j--)
232              picIsrTable[j]=picIsrTable[j-1];
233          picIsrTable[i]=irqNum;
234          shifted=1;
235          break;
236       }
237       i++;
238     }
239     if (!shifted) picIsrTable[picIsrTblPtr]=irqNum;
240     if (irqNum >BSP_MICH_IRQ_MAX_OFFSET)
241        GPPIrqInTbl |= (1<< (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET));
242     else     
243        MainIrqInTbl |= (unsigned long long)(1LLU << irqNum);
244     picIsrTblPtr++;
245  }
246#ifdef SHOW_MORE_INIT_SETTINGS
247  val2 = (MainIrqInTbl>>32) & 0xffffffff;
248  val1 = MainIrqInTbl&0xffffffff;
249  printk("irqNum %d, MainIrqInTbl 0x%x%x\n", irqNum, val2, val1);
250  BSP_printPicIsrTbl();
251#endif
252
253}
254
255
256static void CleanMainIrqTbl(int irqNum)
257{
258  int i, j;
259
260  switch (irqNum) {
261    case BSP_MAIN_GPP7_0_IRQ:
262    case BSP_MAIN_GPP15_8_IRQ:
263    case BSP_MAIN_GPP23_16_IRQ:
264    case BSP_MAIN_GPP31_24_IRQ:
265      return;  /* Do nothing, let GPP take care of it */
266      break; 
267  }
268  if ( ((irqNum<BSP_GPP_IRQ_LOWEST_OFFSET) &&
269        ((unsigned long long)(1LLU << irqNum) & MainIrqInTbl)) ||
270       ((irqNum>BSP_MICH_IRQ_MAX_OFFSET) &&
271        (( 1 << (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)) & GPPIrqInTbl)))
272  { /* If entry in table*/
273     for (i=0; i<64; i++) {
274       if (picIsrTable[i]==irqNum) {/*remove it from the entry */
275          /* all other lower priority entries shifted left */
276          for (j=i;j<picIsrTblPtr; j++)
277              picIsrTable[j]=picIsrTable[j+1];
278          if (irqNum >BSP_MICH_IRQ_MAX_OFFSET)
279            GPPIrqInTbl &= ~(1<< (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET));
280          else     
281            MainIrqInTbl &= ~(1LLU << irqNum);
282          picIsrTblPtr--;
283          break;
284       }
285     }
286  }
287}
288
289void BSP_enable_pic_irq(const rtems_irq_number irqNum)
290{
291  unsigned bitNum, regNum;
292  unsigned int level;
293
294  if ( !is_pic_irq(irqNum) )
295        return;
296
297  bitNum = modIrq32(((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET);
298  regNum = divIrq32(((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET);
299
300  rtems_interrupt_disable(level);
301
302  UpdateMainIrqTbl((int) irqNum);
303  BSP_irqMask_cache[regNum] |= (1 << bitNum);
304
305  out_le32(BSP_irqMask_reg[regNum], BSP_irqMask_cache[regNum]);
306  while (in_le32(BSP_irqMask_reg[regNum]) != BSP_irqMask_cache[regNum]);
307
308  rtems_interrupt_enable(level);
309}
310
311void BSP_enable_irq_at_pic(const rtems_irq_number irqNum)
312{
313        BSP_enable_pic_irq(irqNum);
314}
315
316int BSP_disable_irq_at_pic(const rtems_irq_number irqNum)
317{
318  int      rval;
319  unsigned bitNum, regNum;
320  unsigned int level;
321
322  if ( ! is_pic_irq(irqNum) )
323        return -1;
324
325  bitNum = modIrq32(((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET);
326  regNum = divIrq32(((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET);
327
328  rtems_interrupt_disable(level);
329
330  CleanMainIrqTbl((int) irqNum);
331
332  rval = BSP_irqMask_cache[regNum] & (1<<bitNum);
333
334  BSP_irqMask_cache[regNum] &=  ~(1 << bitNum);
335
336  out_le32(BSP_irqMask_reg[regNum], BSP_irqMask_cache[regNum]);
337  while (in_le32(BSP_irqMask_reg[regNum]) != BSP_irqMask_cache[regNum]);
338
339  rtems_interrupt_enable(level);
340
341  return rval ? 1 : 0;
342}
343
344void BSP_disable_pic_irq(const rtems_irq_number irqNum)
345{
346        (void)BSP_disable_irq_at_pic(irqNum);
347}
348
349int BSP_setup_the_pic(rtems_irq_global_settings *config)  /* adapt the same name as shared/irq */
350{
351    int i;
352
353        internal_config   = config;
354        default_rtems_hdl = config->defaultEntry.hdl;
355        rtems_hdl_tbl     = config->irqHdlTbl;
356
357    /* Get ready for discovery BSP */
358    BSP_irqMask_reg[0]= (volatile unsigned int *) (GT64260_REG_BASE + GT_CPU_INT_MASK_LO);
359    BSP_irqMask_reg[1]= (volatile unsigned int *) (GT64260_REG_BASE + GT_CPU_INT_MASK_HI);
360    BSP_irqMask_reg[2]= (volatile unsigned int *) (GT64260_REG_BASE + GT_GPP_Interrupt_Mask);
361
362    BSP_irqCause_reg[0]= (volatile unsigned int *) (GT64260_REG_BASE + GT_MAIN_INT_CAUSE_LO);
363    BSP_irqCause_reg[1]= (volatile unsigned int *) (GT64260_REG_BASE + GT_MAIN_INT_CAUSE_HI);
364    BSP_irqCause_reg[2]= (volatile unsigned int *) (GT64260_REG_BASE + GT_GPP_Interrupt_Cause);
365
366#ifdef EDGE_TRIGGER
367
368    /* Page 401, Table 598:
369     * Comm Unit Arbiter Control register :
370     * bit 10:GPP interrupts as level sensitive(1) or edge sensitive(0).
371     * We set the GPP interrupts to be edge sensitive.
372     * MOTload default is set as level sensitive(1).
373     */
374    outl((inl(GT_CommUnitArb_Ctrl)& (~(1<<10))), GT_CommUnitArb_Ctrl);
375#else
376    outl((inl(GT_CommUnitArb_Ctrl)| (1<<10)), GT_CommUnitArb_Ctrl);
377#endif
378
379#if 0
380    printk("BSP_irqMask_reg[0] = 0x%x, BSP_irqCause_reg[0] 0x%x\n",
381           in_le32(BSP_irqMask_reg[0]),
382           in_le32(BSP_irqCause_reg[0]));
383    printk("BSP_irqMask_reg[1] = 0x%x, BSP_irqCause_reg[1] 0x%x\n",
384           in_le32(BSP_irqMask_reg[1]),
385           in_le32(BSP_irqCause_reg[1]));
386    printk("BSP_irqMask_reg[2] = 0x%x, BSP_irqCause_reg[2] 0x%x\n",
387           in_le32(BSP_irqMask_reg[2]),
388           in_le32(BSP_irqCause_reg[2]));
389#endif
390
391    /* Initialize the interrupt related GT64260 registers */
392    for (i=0; i<3; i++) {
393      out_le32(BSP_irqCause_reg[i], 0);
394      out_le32(BSP_irqMask_reg[i], 0);
395    }         
396    in_le32(BSP_irqMask_reg[2]);
397    compute_pic_masks_from_prio(config);
398
399#if 0
400    printk("BSP_irqMask_reg[0] = 0x%x, BSP_irqCause_reg[0] 0x%x\n",
401           in_le32(BSP_irqMask_reg[0]),
402           in_le32(BSP_irqCause_reg[0]));
403    printk("BSP_irqMask_reg[1] = 0x%x, BSP_irqCause_reg[1] 0x%x\n",
404           in_le32(BSP_irqMask_reg[1]),
405           in_le32(BSP_irqCause_reg[1]));
406    printk("BSP_irqMask_reg[2] = 0x%x, BSP_irqCause_reg[2] 0x%x\n",
407           in_le32(BSP_irqMask_reg[2]),
408           in_le32(BSP_irqCause_reg[2]));
409#endif
410
411    return(1);
412}
413
414/*
415 * This function check that the value given for the irq line
416 * is valid.
417 */
418
419/*
420 * High level IRQ handler called from shared_raw_irq_code_entry
421 */
422
423int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum)
424{
425  unsigned long irqCause[3]={0, 0,0};
426  register unsigned long selectCause;
427  unsigned oldMask[3]={0,0,0};
428  register unsigned i=0, j, irq=0, bitmask=0, group=0;
429
430  if (excNum == ASM_DEC_VECTOR) {
431
432        bsp_irq_dispatch_list( rtems_hdl_tbl, BSP_DECREMENTER, default_rtems_hdl);
433
434    return 0;
435   
436  }
437
438  for (j=0; j<3; j++ ) oldMask[j] = BSP_irqMask_cache[j];
439
440  if ((selectCause= in_le32((volatile unsigned *)0xf1000c70)) & HI_INT_CAUSE ){
441    irqCause[1] = (selectCause & BSP_irqMask_cache[1]);
442    irqCause[2] = in_le32(BSP_irqCause_reg[2]) & BSP_irqMask_cache[2];
443  }
444  else {
445    irqCause[0] = (selectCause & BSP_irqMask_cache[0]);
446    if ((irqCause[1] =(in_le32((volatile unsigned *)0xf1000c68)&BSP_irqMask_cache[1])))
447       irqCause[2] = in_le32(BSP_irqCause_reg[2]) & BSP_irqMask_cache[2];
448  }
449 
450  while ((irq = picIsrTable[i++])!=-1)
451  {
452    if (irqCause[group=(irq/32)] && (irqCause[group]&(bitmask=(1<<(irq % 32))))) {
453      for (j=0; j<3; j++)
454        BSP_irqMask_cache[j] &= (~ BSP_irq_prio_mask_tbl[j][irq]);
455
456      RTEMS_COMPILER_MEMORY_BARRIER();
457      out_le32((volatile unsigned *)0xf1000c1c, BSP_irqMask_cache[0]);
458      out_le32((volatile unsigned *)0xf1000c6c, BSP_irqMask_cache[1]);
459      out_le32((volatile unsigned *)0xf100f10c, BSP_irqMask_cache[2]);
460      in_le32((volatile unsigned *)0xf100f10c);
461
462#ifdef EDGE_TRIGGER
463      if (irq > BSP_MICH_IRQ_MAX_OFFSET)
464         out_le32(BSP_irqCause_reg[2], ~bitmask);/* Till Straumann: Ack the edge triggered GPP IRQ */
465#endif
466
467          bsp_irq_dispatch_list( rtems_hdl_tbl, irq, default_rtems_hdl);
468     
469      for (j=0; j<3; j++ ) BSP_irqMask_cache[j] = oldMask[j];
470      break;
471    }
472  }
473
474  out_le32((volatile unsigned *)0xf1000c1c, oldMask[0]);
475  out_le32((volatile unsigned *)0xf1000c6c, oldMask[1]);
476  out_le32((volatile unsigned *)0xf100f10c, oldMask[2]);
477  in_le32((volatile unsigned *)0xf100f10c);
478
479  return 0;
480}
481
482/* Only print part of the entries for now */
483void BSP_printPicIsrTbl()
484{
485  int i;
486
487  printk("picIsrTable[12]={");
488  for (i=0; i<12; i++)
489    printk("%d,", picIsrTable[i]);
490  printk("}\n");
491
492  printk("GPPIrqInTbl: 0x%x :\n", GPPIrqInTbl);
493}
Note: See TracBrowser for help on using the repository browser.