source: rtems/c/src/lib/libbsp/powerpc/haleakala/irq/irq.c @ bc98089

4.104.115
Last change on this file since bc98089 was 378bea5, checked in by Ralf Corsepius <ralf.corsepius@…>, on 08/20/08 at 03:41:07

Add missing prototypes.

  • Property mode set to 100644
File size: 8.5 KB
Line 
1/*
2 *
3 *
4 *  The license and distribution terms for this file may be
5 *  found in found in the file LICENSE in this distribution or at
6 *  http://www.rtems.com/license/LICENSE.
7 *
8 *  Middleware support for PPC405 by M.Hamel ADInstruments Ltd 2008
9 *
10 *  $Id$
11 */
12
13#include <rtems.h>
14#include <bsp.h>
15#include <bsp/irq.h>
16#include <bsp/irq_supp.h>
17#include <libcpu/raw_exception.h>
18#include <libcpu/powerpc-utility.h>
19
20
21/* PPC405EX UIC numbers */
22#define UIC_DCR_BASE 0xc0
23#define UIC0_SR      (UIC_DCR_BASE+0x0)  /* UIC status                       */
24#define UIC0_SRS     (UIC_DCR_BASE+0x1)  /* UIC status set                   */
25#define UIC0_ER      (UIC_DCR_BASE+0x2)  /* UIC enable                       */
26#define UIC0_CR      (UIC_DCR_BASE+0x3)  /* UIC critical                     */
27#define UIC0_PR      (UIC_DCR_BASE+0x4)  /* UIC polarity                     */
28#define UIC0_TR      (UIC_DCR_BASE+0x5)  /* UIC triggering                   */
29#define UIC0_MSR     (UIC_DCR_BASE+0x6)  /* UIC masked status                */
30#define UIC0_VR      (UIC_DCR_BASE+0x7)  /* UIC vector                       */
31#define UIC0_VCR     (UIC_DCR_BASE+0x8)  /* UIC vector configuration         */
32
33#define UIC1_SR      (UIC_DCR_BASE+0x10)  /* UIC status                       */
34#define UIC1_SRS     (UIC_DCR_BASE+0x11)  /* UIC status set                   */
35#define UIC1_ER      (UIC_DCR_BASE+0x12)  /* UIC enable                       */
36#define UIC1_CR      (UIC_DCR_BASE+0x13)  /* UIC critical                     */
37#define UIC1_PR      (UIC_DCR_BASE+0x14)  /* UIC polarity                     */
38#define UIC1_TR      (UIC_DCR_BASE+0x15)  /* UIC triggering                   */
39#define UIC1_MSR     (UIC_DCR_BASE+0x16)  /* UIC masked status                */
40#define UIC1_VR      (UIC_DCR_BASE+0x17)  /* UIC vector                       */
41#define UIC1_VCR     (UIC_DCR_BASE+0x18)  /* UIC vector configuration         */
42
43#define UIC2_SR      (UIC_DCR_BASE+0x20)  /* UIC status                       */
44#define UIC2_SRS     (UIC_DCR_BASE+0x21)  /* UIC status set                   */
45#define UIC2_ER      (UIC_DCR_BASE+0x22)  /* UIC enable                       */
46#define UIC2_CR      (UIC_DCR_BASE+0x23)  /* UIC critical                     */
47#define UIC2_PR      (UIC_DCR_BASE+0x24)  /* UIC polarity                     */
48#define UIC2_TR      (UIC_DCR_BASE+0x25)  /* UIC triggering                   */
49#define UIC2_MSR     (UIC_DCR_BASE+0x26)  /* UIC masked status                */
50#define UIC2_VR      (UIC_DCR_BASE+0x27)  /* UIC vector                       */
51#define UIC2_VCR     (UIC_DCR_BASE+0x28)  /* UIC vector configuration         */
52
53enum { kUICWords = 3 };
54
55static rtems_irq_connect_data* rtems_hdl_tblP;
56static rtems_irq_connect_data  dflt_entry;
57
58static uint32_t gEnabledInts[kUICWords];                /* 1-bits mean enabled */
59static uint32_t gIntInhibited[kUICWords];               /* 1-bits disable, overriding gEnabledInts because the interrupt
60                                                                                                   is being processed in C_dispatch_irq_handler */
61
62static inline int IsUICIRQ(const rtems_irq_number irqLine)
63{
64  return (((int) irqLine <= BSP_UIC_IRQ_MAX_OFFSET) &&
65          ((int) irqLine >= BSP_UIC_IRQ_LOWEST_OFFSET)
66         );
67}
68
69static void WriteIState(void)
70/* Write the gEnabledInts state masked by gIntInhibited to the hardware */
71{
72        PPC_SET_DEVICE_CONTROL_REGISTER(UIC0_ER,
73                                        gEnabledInts[0] & ~gIntInhibited[0]);
74        PPC_SET_DEVICE_CONTROL_REGISTER(UIC1_ER,
75                                        gEnabledInts[1] & ~gIntInhibited[1]);
76        PPC_SET_DEVICE_CONTROL_REGISTER(UIC2_ER,
77                                        gEnabledInts[2] & ~gIntInhibited[2]);
78}
79
80void
81BSP_enable_irq_at_pic(const rtems_irq_number irq)
82/* Enable an interrupt; this can be called from inside C_dispatch_irq_handler */
83{
84        if (IsUICIRQ(irq)) {
85                /* Set relevant bit in the state, write state to the UIC */
86                gEnabledInts[irq>>5] |= (0x80000000 >> (irq & 0x1F));
87                WriteIState();
88        }
89}
90
91int
92BSP_disable_irq_at_pic(const rtems_irq_number irq)
93/* Enable an interrupt; this can be called from inside C_dispatch_irq_handler */
94{
95        if (IsUICIRQ(irq)) {
96                uint32_t oldState;
97                int              iword = irq>>5;
98                uint32_t mask = (0x80000000 >> (irq & 0x1F));
99               
100                oldState = gEnabledInts[iword] & mask;
101                gEnabledInts[iword] &= ~mask;
102                WriteIState();
103                return oldState ? 1 : 0;
104        } else
105                return -1;
106}
107
108int
109BSP_setup_the_pic(rtems_irq_global_settings* config)
110{
111        int i;
112       
113        dflt_entry     = config->defaultEntry;
114        rtems_hdl_tblP = config->irqHdlTbl;
115        for (i=0; i<kUICWords; i++)
116                gIntInhibited[i] = 0;
117               
118        /* disable all interrupts */
119        PPC_SET_DEVICE_CONTROL_REGISTER (UIC2_ER, 0x00000000); 
120        /* Set Critical / Non Critical interrupts */
121        PPC_SET_DEVICE_CONTROL_REGISTER (UIC2_CR, 0x00000000);
122        /* Set Interrupt Polarities */
123        PPC_SET_DEVICE_CONTROL_REGISTER (UIC2_PR, 0xf7ffffff);
124        /* Set Interrupt Trigger Levels */
125        PPC_SET_DEVICE_CONTROL_REGISTER (UIC2_TR, 0x01e1fff8);
126        /* Set Vect base=0,INT31 Highest priority */
127        PPC_SET_DEVICE_CONTROL_REGISTER (UIC2_VR, 0x00000001);
128        /* clear all interrupts */
129        PPC_SET_DEVICE_CONTROL_REGISTER (UIC2_SR, 0xffffffff);
130
131        /* disable all interrupts */
132        PPC_SET_DEVICE_CONTROL_REGISTER (UIC1_ER, 0x00000000);
133        /* Set Critical / Non Critical interrupts */
134        PPC_SET_DEVICE_CONTROL_REGISTER (UIC1_CR, 0x00000000);
135        /* Set Interrupt Polarities */
136        PPC_SET_DEVICE_CONTROL_REGISTER (UIC1_PR, 0xfffac785);
137        /* Set Interrupt Trigger Levels */
138        PPC_SET_DEVICE_CONTROL_REGISTER (UIC1_TR, 0x001d0040);
139        /* Set Vect base=0,INT31 Highest priority */
140        PPC_SET_DEVICE_CONTROL_REGISTER (UIC1_VR, 0x00000001);
141        /* clear all interrupts */
142        PPC_SET_DEVICE_CONTROL_REGISTER (UIC1_SR, 0xffffffff);
143
144        /* Disable all interrupts except cascade UIC0 and UIC1 */
145        PPC_SET_DEVICE_CONTROL_REGISTER (UIC0_ER, 0x0000000a);
146        /* Set Critical / Non Critical interrupts */
147        PPC_SET_DEVICE_CONTROL_REGISTER (UIC0_CR, 0x00000000);
148        /* Set Interrupt Polarities */
149        PPC_SET_DEVICE_CONTROL_REGISTER (UIC0_PR, 0xffbfefef);
150        /* Set Interrupt Trigger Levels */
151        PPC_SET_DEVICE_CONTROL_REGISTER (UIC0_TR, 0x00007000);
152        /* Set Vect base=0,INT31 Highest priority */
153        PPC_SET_DEVICE_CONTROL_REGISTER (UIC0_VR, 0x00000001);
154        /* clear all interrupts */
155        PPC_SET_DEVICE_CONTROL_REGISTER (UIC0_SR, 0xffffffff);
156       
157        return 1;
158}
159
160
161/*
162 * High level IRQ handler called from shared_raw_irq_code_entry; decode and
163 * dispatch. Note that this routine needs to be re-entrant
164 *
165 * No support for critical interrupts here yet
166 */
167 
168int
169C_dispatch_irq_handler( struct _BSP_Exception_frame* frame, unsigned int excNum )
170{
171        if (excNum == ASM_EXT_VECTOR) {
172                uint32_t active[kUICWords];
173
174                /* Fetch the masked flags that tell us what external ints are active.
175                   Likely to be only one, but we need to handle more than one,
176                   OR the flags into gIntInhibited */
177                active[0] = PPC_DEVICE_CONTROL_REGISTER(UIC0_MSR);
178                active[1] = PPC_DEVICE_CONTROL_REGISTER(UIC1_MSR);
179                active[2] = PPC_DEVICE_CONTROL_REGISTER(UIC2_MSR);
180                gIntInhibited[0] |= active[0];
181                gIntInhibited[1] |= active[1];
182                gIntInhibited[2] |= active[2];
183               
184                /*  ...and update the hardware so the active interrupts are disabled */
185                WriteIState();
186               
187                /* Loop, calling bsp_irq_dispatch_list for each active interrupt */
188                while ((active[0] | active[1] | active[2]) != 0) {
189                        uint32_t index = -1;
190                        uint32_t bit, bmask;
191                       
192                        /* Find an active interrupt, searching 0..2, bit 0..bit 31 (IBM order) */
193                        do {
194                                index++;
195                                asm volatile (" cntlzw %0, %1":"=r" (bit):"r" (active[index]));
196                        } while (bit==32);
197
198                        /* Call the matching handler */
199                        bsp_irq_dispatch_list(rtems_hdl_tblP, (index*32)+bit, dflt_entry.hdl);
200
201                        /* Write a 1-bit to the appropriate status register to clear it */
202                        bmask = 0x80000000 >> bit;
203                        switch (index) {
204                        case 0:
205                          PPC_SET_DEVICE_CONTROL_REGISTER(UIC0_SR, bmask);
206                          break;
207                        case 1:
208                          PPC_SET_DEVICE_CONTROL_REGISTER(UIC1_SR, bmask);
209                          break;
210                        case 2:
211                          PPC_SET_DEVICE_CONTROL_REGISTER(UIC2_SR, bmask);
212                          break;
213                        }
214                       
215                        /* Clear in the active record and gIntInhibited */
216                        active[index] &= ~bmask;
217                        gIntInhibited[index] &= ~bmask;
218                };
219
220                /* Update the hardware again so the interrupts we have handled are unmasked */
221                WriteIState();
222                return 0;
223               
224        } else if (excNum == ASM_DEC_VECTOR) {          /* 0x1000 remapped by C_dispatch_dec_handler_bookE  */
225                bsp_irq_dispatch_list(rtems_hdl_tblP, BSP_PIT, dflt_entry.hdl);
226                return 0;
227               
228        } else if (excNum == ASM_BOOKE_FIT_VECTOR) {            /* 0x1010 mapped to 0x13 by ppc_get_vector_addr */
229                bsp_irq_dispatch_list(rtems_hdl_tblP, BSP_FIT, dflt_entry.hdl);
230                return 0;
231               
232        } else if (excNum == ASM_BOOKE_WDOG_VECTOR) {           /* 0x1020 mapped to 0x14 by ppc_get_vector_addr */
233                bsp_irq_dispatch_list(rtems_hdl_tblP, BSP_WDOG, dflt_entry.hdl);
234                return 0;
235               
236        } else
237                return -1; /* unhandled interrupt, panic time */
238}
239
Note: See TracBrowser for help on using the repository browser.