source: rtems/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.c @ 89fcd5ca

4.104.114.84.95
Last change on this file since 89fcd5ca was 89fcd5ca, checked in by Joel Sherrill <joel.sherrill@…>, on 11/01/02 at 22:55:52

2002-11-01 Joel Sherrill <joel@…>

  • irq/irq.c, irq/irq_asm.S, startup/bspstart.c: Fixed typos and removed warnings.
  • Property mode set to 100644
File size: 14.2 KB
RevLine 
[5edbffe]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
[d36d3a3]9+  *    21/4/2002 Added support for nested interrupts and improved
10+  *    masking operations.  Now we compute priority mask based
11+  *            on table in irq_init.c
[5edbffe]12 *
13 *  The license and distribution terms for this file may be
14 *  found in found in the file LICENSE in this distribution or at
15 *  http://www.OARcorp.com/rtems/license.html.
16 *
17 *  $Id$
18 */
19 
20#include <bsp.h>
21#include <bsp/irq.h>
[89fcd5ca]22#include <rtems.h>
23#include <rtems/bspIo.h>
[5edbffe]24#include <libcpu/raw_exception.h>
25#include <bsp/vectors.h>
26#include <mpc8260.h>
27
28/*
29 * default handler connected on each irq after bsp initialization
30 */
31static rtems_irq_connect_data   default_rtems_entry;
32
33/*
34 * location used to store initial tables used for interrupt
35 * management.
36 */
37static rtems_irq_global_settings*       internal_config;
38static rtems_irq_connect_data*          rtems_hdl_tbl;
39
40
41/*
42 * Check if symbolic IRQ name is an CPM IRQ
43 */
44static inline int is_cpm_irq(const rtems_irq_symbolic_name irqLine)
45{
[d36d3a3]46        return (((int) irqLine <= BSP_CPM_IRQ_MAX_OFFSET) &
47                        ((int) irqLine >= BSP_CPM_IRQ_LOWEST_OFFSET)
48        );
[5edbffe]49}
50
51/*
52 * Check if symbolic IRQ name is a Processor IRQ
53 */
54static inline int is_processor_irq(const rtems_irq_symbolic_name irqLine)
55{
[d36d3a3]56        return (((int) irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) &
57                        ((int) irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET)
58        );
[5edbffe]59}
60
[d36d3a3]61typedef struct {
62        rtems_unsigned32 mask_h;        /* mask for sipnr_h and simr_h */
63        rtems_unsigned32 mask_l;        /* mask for sipnr_l and simr_l */
64        rtems_unsigned32 priority_h;  /* mask this and lower priority ints */
65        rtems_unsigned32 priority_l;
66} m82xxIrqMasks_t;
[5edbffe]67
68/*
[d36d3a3]69 *  Mask fields should have a '1' in the bit position for that
70 *  interrupt.
71 *      Priority masks calculated later based on priority table
[5edbffe]72 */
[d36d3a3]73
74static m82xxIrqMasks_t SIU_MaskBit[BSP_CPM_IRQ_NUMBER] =
[5edbffe]75{
[d36d3a3]76        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* err */
77        { 0x00000000, 0x00008000, 0x00000000, 0x00000000 }, /* i2c */
78        { 0x00000000, 0x00004000, 0x00000000, 0x00000000 }, /* spi */
79        { 0x00000000, 0x00002000, 0x00000000, 0x00000000 }, /* rtt */
80        { 0x00000000, 0x00001000, 0x00000000, 0x00000000 }, /* smc1 */
81        { 0x00000000, 0x00000800, 0x00000000, 0x00000000 }, /* smc2 */
82        { 0x00000000, 0x00000400, 0x00000000, 0x00000000 }, /* idma1 */
83        { 0x00000000, 0x00000200, 0x00000000, 0x00000000 }, /* idma2 */
84        { 0x00000000, 0x00000100, 0x00000000, 0x00000000 }, /* idma3 */
85        { 0x00000000, 0x00000080, 0x00000000, 0x00000000 }, /* idma4 */
86        { 0x00000000, 0x00000040, 0x00000000, 0x00000000 }, /* sdma */
87        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
88        { 0x00000000, 0x00000010, 0x00000000, 0x00000000 }, /* tmr1 */
89        { 0x00000000, 0x00000008, 0x00000000, 0x00000000 }, /* tmr2 */
90        { 0x00000000, 0x00000004, 0x00000000, 0x00000000 }, /* tmr3 */
91        { 0x00000000, 0x00000002, 0x00000000, 0x00000000 }, /* tmr4 */
92        { 0x00000004, 0x00000000, 0x00000000, 0x00000000 }, /* tmcnt */
93        { 0x00000002, 0x00000000, 0x00000000, 0x00000000 }, /* pit */
94        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
95        { 0x00004000, 0x00000000, 0x00000000, 0x00000000 }, /* irq1 */
96        { 0x00002000, 0x00000000, 0x00000000, 0x00000000 }, /* irq2 */
97        { 0x00001000, 0x00000000, 0x00000000, 0x00000000 }, /* irq3 */
98        { 0x00000800, 0x00000000, 0x00000000, 0x00000000 }, /* irq4 */
99        { 0x00000400, 0x00000000, 0x00000000, 0x00000000 }, /* irq5 */
100        { 0x00000200, 0x00000000, 0x00000000, 0x00000000 }, /* irq6 */
101        { 0x00000100, 0x00000000, 0x00000000, 0x00000000 }, /* irq7 */
102        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
103        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
104        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
105        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
106        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
107        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
108        { 0x00000000, 0x80000000, 0x00000000, 0x00000000 }, /* fcc1 */
109        { 0x00000000, 0x40000000, 0x00000000, 0x00000000 }, /* fcc2 */
110        { 0x00000000, 0x20000000, 0x00000000, 0x00000000 }, /* fcc3 */
111        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
112        { 0x00000000, 0x08000000, 0x00000000, 0x00000000 }, /* mcc1 */
113        { 0x00000000, 0x04000000, 0x00000000, 0x00000000 }, /* mcc2 */
114        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
115        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
116        { 0x00000000, 0x00800000, 0x00000000, 0x00000000 }, /* scc1 */
117        { 0x00000000, 0x00400000, 0x00000000, 0x00000000 }, /* scc2 */
118        { 0x00000000, 0x00200000, 0x00000000, 0x00000000 }, /* scc3 */
119        { 0x00000000, 0x00100000, 0x00000000, 0x00000000 }, /* scc4 */
120        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
121        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
122        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
123        { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
124        { 0x00010000, 0x00000000, 0x00000000, 0x00000000 }, /* pc15 */
125        { 0x00020000, 0x00000000, 0x00000000, 0x00000000 }, /* pc14 */
126        { 0x00040000, 0x00000000, 0x00000000, 0x00000000 }, /* pc13 */
127        { 0x00080000, 0x00000000, 0x00000000, 0x00000000 }, /* pc12 */
128        { 0x00100000, 0x00000000, 0x00000000, 0x00000000 }, /* pc11 */
129        { 0x00200000, 0x00000000, 0x00000000, 0x00000000 }, /* pc10 */
130        { 0x00400000, 0x00000000, 0x00000000, 0x00000000 }, /* pc9 */
131        { 0x00800000, 0x00000000, 0x00000000, 0x00000000 }, /* pc8 */
132        { 0x01000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc7 */
133        { 0x02000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc6 */
134        { 0x04000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc5 */
135        { 0x08000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc4 */
136        { 0x10000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc3 */
137        { 0x20000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc2 */
138        { 0x40000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc1 */
139        { 0x80000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc0 */
140
[5edbffe]141};
142
[d36d3a3]143
144
145void dump_irq_masks(void )
146{
147        int i;
148        for( i=0; i<BSP_CPM_IRQ_NUMBER;i++ )   
149        {
150                printk( "%04d: %08X %08X\n",
151                        i,
152                        SIU_MaskBit[i].priority_h,
153                        SIU_MaskBit[i].priority_l
154                );
155        }
156}
157
[5edbffe]158/*
159 * ------------------------ RTEMS Irq helper functions ----------------
160 */
161
162/*
163 * Caution : this function assumes the variable "internal_config"
164 * is already set and that the tables it contains are still valid
165 * and accessible.
166 */
167static void compute_SIU_IvectMask_from_prio ()
168{
[d36d3a3]169        /*
170         * The actual masks defined
171         * correspond to the priorities defined
172         * for the SIU in irq_init.c.
173         */
174       
175         int i,j;
176       
177         for( i=0; i<BSP_CPM_IRQ_NUMBER; i++ )
178         {
179                for( j=0;j<BSP_CPM_IRQ_NUMBER; j++ )
180                        if( internal_config->irqPrioTbl[j] < internal_config->irqPrioTbl[i] )
181                        {
182                                SIU_MaskBit[i].priority_h |= SIU_MaskBit[j].mask_h;
183                                SIU_MaskBit[i].priority_l |= SIU_MaskBit[j].mask_l;
184                        }                               
185         }
186       
[5edbffe]187}
188
189/*
190 * This function check that the value given for the irq line
191 * is valid.
192 */
193
194static int isValidInterrupt(int irq)
195{
[d36d3a3]196        if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET) )
197                return 0;
198        return 1;
[5edbffe]199}
200
201int BSP_irq_enable_at_cpm(const rtems_irq_symbolic_name irqLine)
202{
[d36d3a3]203        int cpm_irq_index;
[5edbffe]204
[d36d3a3]205        if (!is_cpm_irq(irqLine))
206                return 1;
[5edbffe]207
[d36d3a3]208        cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
[5edbffe]209
[d36d3a3]210        m8260.simr_h |= SIU_MaskBit[cpm_irq_index].mask_h;
211        m8260.simr_l |= SIU_MaskBit[cpm_irq_index].mask_l;
[5edbffe]212
[d36d3a3]213        return 0;
[5edbffe]214}
215
216int BSP_irq_disable_at_cpm(const rtems_irq_symbolic_name irqLine)
217{
[d36d3a3]218        int cpm_irq_index;
[5edbffe]219 
[d36d3a3]220        if (!is_cpm_irq(irqLine))
221                return 1;
[5edbffe]222 
[d36d3a3]223        cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
[5edbffe]224
[d36d3a3]225        m8260.simr_h &= ~(SIU_MaskBit[cpm_irq_index].mask_h);
226        m8260.simr_l &= ~(SIU_MaskBit[cpm_irq_index].mask_l);
[5edbffe]227
228
[d36d3a3]229        return 0;
[5edbffe]230}
231
232int BSP_irq_enabled_at_cpm(const rtems_irq_symbolic_name irqLine)
233{
[d36d3a3]234        int cpm_irq_index;
[5edbffe]235 
[d36d3a3]236        if (!is_cpm_irq(irqLine))
237                return 0;
[5edbffe]238 
[d36d3a3]239        cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
[5edbffe]240
[d36d3a3]241        return ((m8260.simr_h & SIU_MaskBit[cpm_irq_index].mask_h) ||
242                    (m8260.simr_l & SIU_MaskBit[cpm_irq_index].mask_l));
[5edbffe]243}
244
245
246/*
247 * ------------------------ RTEMS Single Irq Handler Mngt Routines ----------------
248 */
249
250int BSP_install_rtems_irq_handler  (const rtems_irq_connect_data* irq)
251{
[d36d3a3]252        unsigned int level;
253
254        if (!isValidInterrupt(irq->name)) {
255                printk( "not a valid intr\n" ) ;
256                return 0;
257        }
258        /*
259         * Check if default handler is actually connected. If not issue an error.
260         * You must first get the current handler via i386_get_current_idt_entry
261         * and then disconnect it using i386_delete_idt_entry.
262         * RATIONALE : to always have the same transition by forcing the user
263         * to get the previous handler before accepting to disconnect.
264         */
265        if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
266                printk( "Default handler not there\n" );
267                return 0;
268        }
269
270        _CPU_ISR_Disable(level);
271
272        /*
273         * store the data provided by user
274         */
275        rtems_hdl_tbl[irq->name] = *irq;
276       
277        if (is_cpm_irq(irq->name)) {
278            /*
279             * Enable interrupt at PIC level
280             */
281            BSP_irq_enable_at_cpm (irq->name);
282        }
[5edbffe]283
[d36d3a3]284#if 0
285        if (is_processor_irq(irq->name)) {
286                /*
287                 * Should Enable exception at processor level but not needed.  Will restore
288                 * EE flags at the end of the routine anyway.
289                 */
290        }
291#endif
[5edbffe]292
[d36d3a3]293        /*
294         * Enable interrupt on device
295         */
296        irq->on(irq);
297
298        _CPU_ISR_Enable(level);
299
300        /*
301            printk( "Enabled\n" );
302        */
303        return 1;
[5edbffe]304}
305
306
307int BSP_get_current_rtems_irq_handler   (rtems_irq_connect_data* irq)
308{
[d36d3a3]309        if (!isValidInterrupt(irq->name)) {
310                return 0;
311        }
312        *irq = rtems_hdl_tbl[irq->name];
313        return 1;
[5edbffe]314}
315
316int BSP_remove_rtems_irq_handler  (const rtems_irq_connect_data* irq)
317{
[d36d3a3]318        unsigned int level;
[5edbffe]319 
[d36d3a3]320        if (!isValidInterrupt(irq->name)) {
321                return 0;
322        }
323        /*
324         * Check if default handler is actually connected. If not issue an error.
325         * You must first get the current handler via i386_get_current_idt_entry
326         * and then disconnect it using i386_delete_idt_entry.
327         * RATIONALE : to always have the same transition by forcing the user
328         * to get the previous handler before accepting to disconnect.
329         */
330        if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
331          return 0;
332        }
333        _CPU_ISR_Disable(level);
334       
335        if (is_cpm_irq(irq->name)) {
336          /*
337           * disable interrupt at PIC level
338           */
339          BSP_irq_disable_at_cpm (irq->name);
340        }
341       
342        if (is_processor_irq(irq->name)) {
343          /*
344           * disable exception at processor level
345           */
346        }   
347       
348        /*
349         * Disable interrupt on device
350         */
351        irq->off(irq);
352       
353        /*
354         * restore the default irq value
355         */
356        rtems_hdl_tbl[irq->name] = default_rtems_entry;
357       
358        _CPU_ISR_Enable(level);
359       
360        return 1;
[5edbffe]361}
362
363/*
364 * ------------------------ RTEMS Global Irq Handler Mngt Routines ----------------
365 */
366
367int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
368{
[d36d3a3]369        int i;
370        unsigned int level;
371        /*
372         * Store various code accelerators
373         */
374        internal_config                 = config;
375        default_rtems_entry             = config->defaultEntry;
376        rtems_hdl_tbl           = config->irqHdlTbl;
377
378        /* Fill in priority masks */
379        compute_SIU_IvectMask_from_prio();
380       
381        _CPU_ISR_Disable(level);
382        /*
383         * start with CPM IRQ
384         */
385        for (i=BSP_CPM_IRQ_LOWEST_OFFSET; i < BSP_CPM_IRQ_LOWEST_OFFSET + BSP_CPM_IRQ_NUMBER ; i++) {
386                if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
387                        BSP_irq_enable_at_cpm (i);
388                        rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
389                } else {
390                        rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
391                        BSP_irq_disable_at_cpm (i);
392                }
393        }
394
395        /*
396         * finish with Processor exceptions handled like IRQ
397         */
398        for (i=BSP_PROCESSOR_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER; i++) {
399                if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
400                        rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
401                } else {
402                        rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
403                }
404        }
405
406        _CPU_ISR_Enable(level);
407        return 1;
[5edbffe]408}
409
410int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
411{
[d36d3a3]412        *config = internal_config;
413        return 0;
[5edbffe]414}
415
416#ifdef DISPATCH_HANDLER_STAT
417volatile unsigned int maxLoop = 0;
418#endif
419
[d36d3a3]420
[5edbffe]421/*
422 * High level IRQ handler called from shared_raw_irq_code_entry
423 */
424void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum)
425{
[d36d3a3]426        register unsigned int irq;
[5edbffe]427#if 0
[d36d3a3]428        register unsigned oldMask;                    /* old siu pic masks */
[5edbffe]429#endif
[d36d3a3]430        register unsigned msr;
431        register unsigned new_msr;
432        register unsigned old_simr_h;
433        register unsigned old_simr_l;
[5edbffe]434#ifdef DISPATCH_HANDLER_STAT
[d36d3a3]435        unsigned loopCounter;
[5edbffe]436#endif
437
438
439
[d36d3a3]440        /*
441         * Handle decrementer interrupt
442         */
443        if (excNum == ASM_DEC_VECTOR) {
444                _CPU_MSR_GET(msr);
445                new_msr = msr | MSR_EE;
446                _CPU_MSR_SET(new_msr);
[5edbffe]447
[d36d3a3]448                rtems_hdl_tbl[BSP_DECREMENTER].hdl();
[5edbffe]449
[d36d3a3]450                _CPU_MSR_SET(msr);
[5edbffe]451
[d36d3a3]452                return;
453        }
[5edbffe]454
[d36d3a3]455        /*
456         * Handle external interrupt generated by SIU on PPC core
457         */
[5edbffe]458#ifdef DISPATCH_HANDLER_STAT
[d36d3a3]459        loopCounter = 0;
[5edbffe]460#endif 
461
[d36d3a3]462        while (1) {
463
464                if( ((m8260.sipnr_h & m8260.simr_h) | (m8260.sipnr_l & m8260.simr_l)) == 0 ) {
[5edbffe]465#ifdef DISPATCH_HANDLER_STAT
[d36d3a3]466                        if (loopCounter >  maxLoop) maxLoop = loopCounter;
[5edbffe]467#endif     
[d36d3a3]468                        break;
469                }
470
471                irq = (m8260.sivec >> 26) + BSP_CPM_IRQ_LOWEST_OFFSET;
472
473                /* Clear mask and pending register */
474                if( irq <= BSP_CPM_IRQ_MAX_OFFSET ) {
475                        /* save interrupt masks */
476                        old_simr_h = m8260.simr_h;
477                        old_simr_l = m8260.simr_l;
478
479                        /* mask off current interrupt and lower priority ones */
480                        m8260.simr_h &= SIU_MaskBit[irq].priority_h;
481                        m8260.simr_l &= SIU_MaskBit[irq].priority_l;
482
483                        /* clear pending bit */
484                        m8260.sipnr_h |= SIU_MaskBit[irq].mask_h;
485                        m8260.sipnr_l |= SIU_MaskBit[irq].mask_l;
486
487                        /* re-enable external exceptions */
488                        _CPU_MSR_GET(msr);
489                        new_msr = msr | MSR_EE;
490                        _CPU_MSR_SET(new_msr);
491
492                        /* call handler */
493                        rtems_hdl_tbl[irq].hdl();
494
495                        /* disable exceptions again */
496                        _CPU_MSR_SET(msr);
497                       
498                        /* restore interrupt masks */
499                        m8260.simr_h = old_simr_h;
500                        m8260.simr_l = old_simr_l;
501                       
502                }
[5edbffe]503#ifdef DISPATCH_HANDLER_STAT
[d36d3a3]504                ++ loopCounter;
505#endif
506        }
[5edbffe]507}
508
509   
510 
511void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
512{
[d36d3a3]513        /*
514         * Process pending signals that have not already been
515         * processed by _Thread_Displatch. This happens quite
516         * unfrequently : the ISR must have posted an action
517         * to the current running thread.
518         */
519        if ( _Thread_Do_post_task_switch_extension ||
520                _Thread_Executing->do_post_task_switch_extension ) {
521                _Thread_Executing->do_post_task_switch_extension = FALSE;
522                _API_extensions_Run_postswitch();
523        }
524
525        /*
526         * I plan to process other thread related events here.
527         * This will include DEBUG session requested from keyboard...
528         */
[5edbffe]529}
Note: See TracBrowser for help on using the repository browser.