source: rtems/bsps/powerpc/mvme5500/irq/BSP_irq.c @ 3fe2155

5
Last change on this file since 3fe2155 was 3fe2155, checked in by Sebastian Huber <sebastian.huber@…>, on 02/01/19 at 09:00:36

Remove superfluous <rtems/system.h> includes

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