source: rtems/bsps/powerpc/haleakala/irq/irq.c @ 762fa62

5
Last change on this file since 762fa62 was 8f8ccee, checked in by Sebastian Huber <sebastian.huber@…>, on 04/23/18 at 07:50:39

bsps: Move interrupt controller support to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

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