source: rtems/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.c @ 5edbffe

4.104.114.84.95
Last change on this file since 5edbffe was 5edbffe, checked in by Joel Sherrill <joel.sherrill@…>, on Oct 22, 2001 at 2:46:02 PM

01-10-22 Andy Dachs <a.dachs@…>

  • mpc8260ads added as new BSP. tm27 reported not to run at this time.
  • ChangeLog?, Makefile.am, README, aclocal.m4, bsp_specs, clock/.cvsignore, clock/Makefile.am, clock/p_clock.c, configure.in, console/Makefile.am, console/console.c, include/Makefile.am, include/bsp.h, include/coverhd.h, irq/.cvsignore, irq/Makefile.am, irq/irq.c, irq/irq.h, irq/irq_asm.S, irq/irq_init.c, network/Makefile.am, network/README, network/if_hdlcsubr.c, network/if_hdlcsubr.h, network/network.c, start/Makefile.am, start/start.S, startup/Makefile.am, startup/bspstart.c, startup/cpuinit.c, startup/linkcmds, startup/setvec.c, times, vectors/.cvsignore, vectors/Makefile.am, vectors/vectors.S, vectors/vectors.h, vectors/vectors_init.c, wrapup/Makefile.am: New files.
  • Property mode set to 100644
File size: 10.8 KB
Line 
1/*
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 *  Modified for mpc8260 Andy Dachs <a.dachs@sstl.co.uk>
8 *  Surrey Satellite Technology Limited, 2000
9 *  Nested exception handlers not working yet.
10 *
11 *  The license and distribution terms for this file may be
12 *  found in found in the file LICENSE in this distribution or at
13 *  http://www.OARcorp.com/rtems/license.html.
14 *
15 *  $Id$
16 */
17 
18#include <bsp.h>
19#include <bsp/irq.h>
20#include <rtems/score/thread.h>
21#include <rtems/score/apiext.h>
22#include <libcpu/raw_exception.h>
23#include <bsp/vectors.h>
24#include <libcpu/cpu.h>
25/*#include <bsp/8xx_immap.h>*/
26#include <mpc8260.h>
27/*#include <bsp/commproc.h>*/
28
29/*
30 * default handler connected on each irq after bsp initialization
31 */
32static rtems_irq_connect_data   default_rtems_entry;
33
34/*
35 * location used to store initial tables used for interrupt
36 * management.
37 */
38static rtems_irq_global_settings*       internal_config;
39static rtems_irq_connect_data*          rtems_hdl_tbl;
40
41
42/*
43 * Check if symbolic IRQ name is an CPM IRQ
44 */
45static inline int is_cpm_irq(const rtems_irq_symbolic_name irqLine)
46{
47  return (((int) irqLine <= BSP_CPM_IRQ_MAX_OFFSET) &
48          ((int) irqLine >= BSP_CPM_IRQ_LOWEST_OFFSET)
49         );
50}
51
52/*
53 * Check if symbolic IRQ name is a Processor IRQ
54 */
55static inline int is_processor_irq(const rtems_irq_symbolic_name irqLine)
56{
57  return (((int) irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) &
58          ((int) irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET)
59         );
60}
61
62
63/*
64 * bit in the SIU mask registers (PPC bit numbering) that should
65 * be set to enable the relevant interrupt
66 *
67 */
68const static unsigned int SIU_MaskBit[BSP_CPM_IRQ_NUMBER] =
69{
70     63, 48, 49, 50,  /* err,   i2c,   spi,   rtt   */
71     51, 52, 53, 54,  /* smc1,  smc2,  idma1, idma2 */
72     55, 56, 57, 63,  /* idma3, idma4, sdma,  -     */
73     59, 60, 61, 62,  /* tmr1,  tmr2,  tmr3,  tmr4  */
74     29, 30, 63, 17,  /* pit,   tmcnt, -,     irq1  */
75     18, 19, 20, 21,  /* irq2,  irq3,  irq4,  irq5  */
76     22, 23, 63, 63,  /* irq6,  irq7,  -,     -     */
77     63, 63, 63, 63,  /* -,     -,     -,     -     */
78     32, 33, 34, 35,  /* fcc1,  fcc2,  fcc3,  -     */
79     36, 37, 38, 39,  /* mcc1,  mcc2,  -,     -     */
80     40, 41, 42, 43,  /* scc1,  scc2,  scc3,  scc4  */
81     44, 45, 46, 47,  /* -,     -,     -,     -     */
82     0,  1,   2,  3,  /* pc0,   pc1,   pc2,   pc3   */
83     4,  5,   6,  7,  /* pc4,   pc5,   pc6,   pc7   */
84     8,  9,  10, 11,  /* pc8,   pc9,   pc10,  pc11  */
85     12, 13, 14, 15   /* pc12,  pc13,  pc14,  pc15  */
86};
87
88/*
89 * ------------------------ RTEMS Irq helper functions ----------------
90 */
91
92/*
93 * Caution : this function assumes the variable "internal_config"
94 * is already set and that the tables it contains are still valid
95 * and accessible.
96 */
97static void compute_SIU_IvectMask_from_prio ()
98{
99  /*
100   * In theory this is feasible. No time to code it yet. See i386/shared/irq.c
101   * for an example based on 8259 controller mask. The actual masks defined
102   * correspond to the priorities defined for the SIU in irq_init.c.
103   */
104}
105
106/*
107 * This function check that the value given for the irq line
108 * is valid.
109 */
110
111static int isValidInterrupt(int irq)
112{
113  if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET) )
114    return 0;
115  return 1;
116}
117
118int BSP_irq_enable_at_cpm(const rtems_irq_symbolic_name irqLine)
119{
120  int cpm_irq_index;
121
122  if (!is_cpm_irq(irqLine))
123    return 1;
124
125  cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
126
127
128  if( SIU_MaskBit[cpm_irq_index] < 32 )
129     m8260.simr_h |= (0x80000000 >> SIU_MaskBit[cpm_irq_index]);
130  else
131     m8260.simr_l |= (0x80000000 >> (SIU_MaskBit[cpm_irq_index]-32));
132
133  return 0;
134}
135
136int BSP_irq_disable_at_cpm(const rtems_irq_symbolic_name irqLine)
137{
138  int cpm_irq_index;
139 
140  if (!is_cpm_irq(irqLine))
141    return 1;
142 
143  cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
144
145  if( SIU_MaskBit[cpm_irq_index] < 32 )
146     m8260.simr_h &= ~(0x80000000 >> SIU_MaskBit[cpm_irq_index]);
147  else
148     m8260.simr_l &= ~(0x80000000 >> (SIU_MaskBit[cpm_irq_index]-32));
149
150
151  return 0;
152}
153
154int BSP_irq_enabled_at_cpm(const rtems_irq_symbolic_name irqLine)
155{
156  int cpm_irq_index;
157 
158  if (!is_cpm_irq(irqLine))
159    return 0;
160 
161  cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
162
163  if( SIU_MaskBit[cpm_irq_index] < 32 )
164     return m8260.simr_h & (0x80000000 >> SIU_MaskBit[cpm_irq_index]);
165  else
166     return m8260.simr_l & (0x80000000 >> (SIU_MaskBit[cpm_irq_index]-32));
167}
168
169
170/*
171 * ------------------------ RTEMS Single Irq Handler Mngt Routines ----------------
172 */
173
174int BSP_install_rtems_irq_handler  (const rtems_irq_connect_data* irq)
175{
176    unsigned int level;
177 
178    if (!isValidInterrupt(irq->name)) {
179      printk( "not a valid intr\n" ) ;
180      return 0;
181    }
182    /*
183     * Check if default handler is actually connected. If not issue an error.
184     * You must first get the current handler via i386_get_current_idt_entry
185     * and then disconnect it using i386_delete_idt_entry.
186     * RATIONALE : to always have the same transition by forcing the user
187     * to get the previous handler before accepting to disconnect.
188     */
189    if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
190      printk( "Default handler not there\n" );
191      return 0;
192    }
193
194    _CPU_ISR_Disable(level);
195
196    /*
197     * store the data provided by user
198     */
199    rtems_hdl_tbl[irq->name] = *irq;
200   
201    if (is_cpm_irq(irq->name)) {
202      /*
203       * Enable interrupt at PIC level
204       */
205      BSP_irq_enable_at_cpm (irq->name);
206    }
207   
208
209    if (is_processor_irq(irq->name)) {
210      /*
211       * Should Enable exception at processor level but not needed.  Will restore
212       * EE flags at the end of the routine anyway.
213       */
214    }
215    /*
216     * Enable interrupt on device
217     */
218    irq->on(irq);
219   
220    _CPU_ISR_Enable(level);
221
222/*
223    printk( "Enabled\n" );
224*/
225    return 1;
226}
227
228
229int BSP_get_current_rtems_irq_handler   (rtems_irq_connect_data* irq)
230{
231     if (!isValidInterrupt(irq->name)) {
232      return 0;
233     }
234     *irq = rtems_hdl_tbl[irq->name];
235     return 1;
236}
237
238int BSP_remove_rtems_irq_handler  (const rtems_irq_connect_data* irq)
239{
240    unsigned int level;
241 
242    if (!isValidInterrupt(irq->name)) {
243      return 0;
244    }
245    /*
246     * Check if default handler is actually connected. If not issue an error.
247     * You must first get the current handler via i386_get_current_idt_entry
248     * and then disconnect it using i386_delete_idt_entry.
249     * RATIONALE : to always have the same transition by forcing the user
250     * to get the previous handler before accepting to disconnect.
251     */
252    if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
253      return 0;
254    }
255    _CPU_ISR_Disable(level);
256
257    if (is_cpm_irq(irq->name)) {
258      /*
259       * disable interrupt at PIC level
260       */
261      BSP_irq_disable_at_cpm (irq->name);
262    }
263
264    if (is_processor_irq(irq->name)) {
265      /*
266       * disable exception at processor level
267       */
268    }   
269
270    /*
271     * Disable interrupt on device
272     */
273    irq->off(irq);
274
275    /*
276     * restore the default irq value
277     */
278    rtems_hdl_tbl[irq->name] = default_rtems_entry;
279
280    _CPU_ISR_Enable(level);
281
282    return 1;
283}
284
285/*
286 * ------------------------ RTEMS Global Irq Handler Mngt Routines ----------------
287 */
288
289int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
290{
291    int i;
292    unsigned int level;
293   /*
294    * Store various code accelerators
295    */
296    internal_config             = config;
297    default_rtems_entry         = config->defaultEntry;
298    rtems_hdl_tbl               = config->irqHdlTbl;
299
300    _CPU_ISR_Disable(level);
301    /*
302     * start with CPM IRQ
303     */
304    for (i=BSP_CPM_IRQ_LOWEST_OFFSET; i < BSP_CPM_IRQ_LOWEST_OFFSET + BSP_CPM_IRQ_NUMBER ; i++) {
305      if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
306        BSP_irq_enable_at_cpm (i);
307        rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
308      }
309      else {
310        rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
311        BSP_irq_disable_at_cpm (i);
312      }
313    }
314
315    /*
316     * finish with Processor exceptions handled like IRQ
317     */
318    for (i=BSP_PROCESSOR_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER; i++) {
319      if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
320        rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
321      }
322      else {
323        rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
324      }
325    }
326    _CPU_ISR_Enable(level);
327    return 1;
328}
329
330int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
331{
332    *config = internal_config;
333    return 0;
334}
335
336#ifdef DISPATCH_HANDLER_STAT
337volatile unsigned int maxLoop = 0;
338#endif
339
340/*
341 * High level IRQ handler called from shared_raw_irq_code_entry
342 */
343void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum)
344{
345  register unsigned int irq;
346#if 0
347  register unsigned oldMask;                  /* old siu pic masks */
348#endif
349  register unsigned msr;
350  register unsigned new_msr;
351#ifdef DISPATCH_HANDLER_STAT
352  unsigned loopCounter;
353#endif
354
355
356
357  /*
358   * Handle decrementer interrupt
359   */
360  if (excNum == ASM_DEC_VECTOR) {
361
362/*
363    _BSP_GPLED1_on();
364*/
365    _CPU_MSR_GET(msr);
366    new_msr = msr | MSR_EE;
367    _CPU_MSR_SET(new_msr);
368
369    rtems_hdl_tbl[BSP_DECREMENTER].hdl();
370
371    _CPU_MSR_SET(msr);
372
373/*
374    _BSP_GPLED1_off();
375*/
376    return;
377  }
378
379  /*
380   * Handle external interrupt generated by SIU on PPC core
381   */
382#ifdef DISPATCH_HANDLER_STAT
383  loopCounter = 0;
384#endif 
385  while (1) {
386
387    if( ((m8260.sipnr_h & m8260.simr_h) | (m8260.sipnr_l & m8260.simr_l)) == 0 ) {
388#ifdef DISPATCH_HANDLER_STAT
389      if (loopCounter >  maxLoop) maxLoop = loopCounter;
390#endif     
391      break;
392    }
393
394    irq = (m8260.sivec >> 26) + BSP_CPM_IRQ_LOWEST_OFFSET;
395
396/*
397    printk( "dispatching %d\n", irq );
398*/
399
400    /* Clear pending register */
401    if( irq <= BSP_CPM_IRQ_MAX_OFFSET ) {
402      if( SIU_MaskBit[irq] < 32 )
403        m8260.sipnr_h = (0x80000000 >> SIU_MaskBit[irq]);
404      else
405        m8260.sipnr_l = (0x80000000 >> (SIU_MaskBit[irq]-32));
406    }
407
408/*
409    _CPU_MSR_GET(msr);
410    new_msr = msr | MSR_EE;
411    _CPU_MSR_SET(new_msr);
412*/
413    rtems_hdl_tbl[irq].hdl();
414/*
415    _CPU_MSR_SET(msr);
416*/
417
418
419
420#if 0
421    ppc_cached_irq_mask |= (oldMask & ~(SIU_IvectMask[irq]));
422    ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
423#endif
424#ifdef DISPATCH_HANDLER_STAT
425    ++ loopCounter;
426#endif   
427  }
428
429
430
431
432}
433
434   
435 
436void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
437{
438  /*
439   * Process pending signals that have not already been
440   * processed by _Thread_Displatch. This happens quite
441   * unfrequently : the ISR must have posted an action
442   * to the current running thread.
443   */
444  if ( _Thread_Do_post_task_switch_extension ||
445       _Thread_Executing->do_post_task_switch_extension ) {
446    _Thread_Executing->do_post_task_switch_extension = FALSE;
447    _API_extensions_Run_postswitch();
448  }
449  /*
450   * I plan to process other thread related events here.
451   * This will include DEBUG session requested from keyboard...
452   */
453}
Note: See TracBrowser for help on using the repository browser.