source: rtems/c/src/lib/libbsp/powerpc/mvme5500/irq/BSP_irq.c @ 2d5c486

4.115
Last change on this file since 2d5c486 was 2d5c486, checked in by Nick Withers <nick.withers@…>, on 11/27/14 at 06:39:36

Use fixed-width C99 types for PowerPC in_be16() and co.

Also use the const qualifier on the address pointer's target in in_*()

Closes #2128

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