source: rtems/c/src/lib/libbsp/powerpc/mvme2307/pci/interrupts.c @ 19ca797

4.104.114.84.95
Last change on this file since 19ca797 was 19ca797, checked in by Joel Sherrill <joel.sherrill@…>, on 10/04/99 at 20:41:28

Motorola MVME2307 BSP submitted by Jay Kulpinski <jskulpin@…>.
No modifications made.

  • Property mode set to 100644
File size: 12.4 KB
Line 
1#include <rtems.h>
2#include <rtems/error.h>
3#include <bsp.h>
4
5#define NUMBER_INTERRUPTS (IRQ_RAVEN_ERROR + 1)
6
7#define DISABLE_IRQ 0x80000000
8
9static rtems_isr raven_interrupt_handler(rtems_vector_number vector);
10static rtems_isr default_interrupt_handler(rtems_vector_number vector);
11static rtems_isr spurious_interrupt_handler(rtems_vector_number vector);
12
13
14static rtems_isr_entry handlers[NUMBER_INTERRUPTS];
15static int *vec_prio_reg_addresses[NUMBER_INTERRUPTS] = {0};
16static void *raven_base = 0;
17static int timer_frequency = 0;
18
19rtems_status_code interrupt_controller_init(void) {
20    int i;
21    int raven_config = pci_find_by_devid(RAVEN_VENDOR_ID, RAVEN_DEVICE_ID, 0);
22    rtems_isr_entry old_handler;
23    rtems_status_code sc;
24
25    /* get base address of raven registers in LOCAL space */
26    raven_base =
27        (void *)PCI_TO_LOCAL(pci_conf_read32(raven_config, PCI_BASE_ADDRESS_1));
28
29    /* set cascade mode in global configuration register */
30    st_le32(raven_base + 0x01020, 0x20000000);
31
32    /* set spurious interrupt vector */
33    st_le32(raven_base + 0x010e0, IRQ_SPURIOUS);
34
35    /* get the timer frequency */
36    timer_frequency = ld_le32(raven_base + 0x010f0);
37
38    /* fill in vector/priority register addresses */
39    vec_prio_reg_addresses[IRQ_PIC_CASCADE] = raven_base + 0x10000;
40    vec_prio_reg_addresses[IRQ_FALCON_ECC]  = raven_base + 0x10020;
41    vec_prio_reg_addresses[IRQ_ETHERNET]    = raven_base + 0x10040;
42    vec_prio_reg_addresses[IRQ_VME_LINT0]   = raven_base + 0x100a0;
43    vec_prio_reg_addresses[IRQ_VME_LINT1]   = raven_base + 0x100c0;
44    vec_prio_reg_addresses[IRQ_VME_LINT2]   = raven_base + 0x100e0;
45    vec_prio_reg_addresses[IRQ_VME_LINT3]   = raven_base + 0x10100;
46    vec_prio_reg_addresses[IRQ_PMC1A_PMC2B] = raven_base + 0x10120;
47    vec_prio_reg_addresses[IRQ_PMC1B_PMC2C] = raven_base + 0x10140;
48    vec_prio_reg_addresses[IRQ_PMC1C_PMC2D] = raven_base + 0x10160;
49    vec_prio_reg_addresses[IRQ_PMC1D_PMC2A] = raven_base + 0x10180;
50    vec_prio_reg_addresses[IRQ_LM_SIG_0]    = raven_base + 0x101a0;
51    vec_prio_reg_addresses[IRQ_LM_SIG_1]    = raven_base + 0x101c0;
52    vec_prio_reg_addresses[IRQ_TIMER_0]     = raven_base + 0x01120;
53    vec_prio_reg_addresses[IRQ_TIMER_1]     = raven_base + 0x01160;
54    vec_prio_reg_addresses[IRQ_TIMER_2]     = raven_base + 0x011a0;
55    vec_prio_reg_addresses[IRQ_TIMER_3]     = raven_base + 0x011e0;
56    vec_prio_reg_addresses[IRQ_IPI_0]       = raven_base + 0x010a0;
57    vec_prio_reg_addresses[IRQ_IPI_1]       = raven_base + 0x010b0;
58    vec_prio_reg_addresses[IRQ_IPI_2]       = raven_base + 0x010c0;
59    vec_prio_reg_addresses[IRQ_IPI_3]       = raven_base + 0x010d0;
60    vec_prio_reg_addresses[IRQ_RAVEN_ERROR] = raven_base + 0x10200;
61
62    /* initialize all vector/priority registers to level 0, disabled */
63    for (i = 0; i < NUMBER_INTERRUPTS; i++) {
64        if (vec_prio_reg_addresses[i]) {
65            st_le32(vec_prio_reg_addresses[i], DISABLE_IRQ | i);
66        }
67    }
68
69    /* initialize all interrupt destination registers to processor 0 */
70    st_le32(raven_base + 0x01130, 1);
71    st_le32(raven_base + 0x01170, 1);
72    st_le32(raven_base + 0x011b0, 1);
73    st_le32(raven_base + 0x011f0, 1);
74    st_le32(raven_base + 0x10010, 1);
75    st_le32(raven_base + 0x10030, 1);
76    st_le32(raven_base + 0x10050, 1);
77    st_le32(raven_base + 0x10070, 1);
78    st_le32(raven_base + 0x10090, 1);
79    st_le32(raven_base + 0x100b0, 1);
80    st_le32(raven_base + 0x100d0, 1);
81    st_le32(raven_base + 0x100f0, 1);
82    st_le32(raven_base + 0x10110, 1);
83    st_le32(raven_base + 0x10130, 1);
84    st_le32(raven_base + 0x10150, 1);
85    st_le32(raven_base + 0x10170, 1);
86    st_le32(raven_base + 0x10190, 1);
87    st_le32(raven_base + 0x101b0, 1);
88    st_le32(raven_base + 0x101d0, 1);
89    st_le32(raven_base + 0x101f0, 1);
90    st_le32(raven_base + 0x10210, 1);
91
92    /* set up default interrupt handlers */
93    for (i = 0; i < NUMBER_INTERRUPTS; i++) {
94        handlers[i] = default_interrupt_handler;
95    }
96    handlers[IRQ_SPURIOUS] = spurious_interrupt_handler;
97
98    /* enable 8259 PIC interrupt at level 8 */
99    st_le32(vec_prio_reg_addresses[IRQ_PIC_CASCADE],
100            0x00c00000 | (PRIORITY_ISA_INT << 16) | IRQ_PIC_CASCADE);
101
102    /* attach interrupt handler and enable interrupts */
103    sc = rtems_interrupt_catch(raven_interrupt_handler, PPC_IRQ_EXTERNAL,
104                               &old_handler);
105    if (sc != RTEMS_SUCCESSFUL) {
106        rtems_panic("can't catch interrupt for raven pic\n");
107    }
108    return set_interrupt_task_priority(0);
109}
110
111#define PCI_Interrupt_Ack_Addr ((unsigned32 *) 0xFEFF0030)
112#define NonspecificEOI 0x20
113#define PIC1_OCW2 (*(volatile char *)IO_TO_LOCAL(0x20))
114#define PIC2_OCW2 (*(volatile char *)IO_TO_LOCAL(0xA0))
115
116static rtems_isr raven_interrupt_handler(rtems_vector_number vector) {
117    int raven_vector;
118    int msr_value;
119
120    /* read Raven interrupt acknowledge register */
121    raven_vector = ld_le32(raven_base + 0x200a0);
122
123    if (raven_vector == IRQ_PIC_CASCADE) {
124        /* read PCI interrupt acknowledge register */
125        int piack_image = ld_le32(PCI_Interrupt_Ack_Addr);
126        int isa_vector = piack_image & 0x07;
127        int pic_id = (piack_image >> 3) & 0x1f;
128       
129        if (pic_id == 0x10) {
130            isa_vector += 8;
131        } else if (pic_id != 0x01) {
132            rtems_panic("unrecognized PIACK value: %08x\n", piack_image);
133        }
134
135        /* set MSRee = 1 */
136        _CPU_MSR_Value(msr_value);
137        msr_value |= PPC_MSR_EE;
138        _CPU_MSR_SET(msr_value);
139
140        /* signal EOI to Raven */
141        st_le32(raven_base + 0x200b0, 0);
142
143        /* call handler */
144        handlers[isa_vector](isa_vector);
145
146        /* signal EOI to 8259 PIC */
147        PIC1_OCW2 = NonspecificEOI;
148        if (isa_vector >= 8) {
149            PIC2_OCW2 = NonspecificEOI;
150        }
151    } else {
152        /* set MSRee = 1 */
153        _CPU_MSR_Value(msr_value);
154        msr_value |= PPC_MSR_EE;
155        _CPU_MSR_SET(msr_value);
156
157        /* call handler */
158        handlers[raven_vector](raven_vector);
159
160        /* signal EOI to Raven */
161        st_le32(raven_base + 0x200b0, 0);
162
163    }
164}
165
166static rtems_isr default_interrupt_handler(rtems_vector_number vector) {
167    rtems_panic("unhandled interrupt: %d\n", vector);
168}
169
170static rtems_isr spurious_interrupt_handler(rtems_vector_number vector) {
171    rtems_panic("spurious interrupt\n");
172}
173
174rtems_status_code bsp_interrupt_catch(rtems_isr_entry      new_isr_handler,
175                                      rtems_vector_number  vector,
176                                      rtems_isr_entry     *old_isr_handler) {
177    if (!old_isr_handler || ((int)new_isr_handler & 3) != 0) {
178        return RTEMS_INVALID_ADDRESS;
179    }
180    switch (vector) {
181                case IRQ_ISA_TIMER:     case IRQ_UART:          case IRQ_ISA_LM_SIG:
182                case IRQ_ABORT_SWITCH:  case IRQ_ISA_ETHERNET:  case IRQ_ISA_UNIVERSE:
183                case IRQ_ISA_PMC_PCIX:  case IRQ_FALCON_ECC:    case IRQ_ETHERNET:
184                case IRQ_VME_LINT0:     case IRQ_VME_LINT1:     case IRQ_VME_LINT2:
185                case IRQ_VME_LINT3:     case IRQ_PMC1A_PMC2B:   case IRQ_PMC1B_PMC2C:
186                case IRQ_PMC1C_PMC2D:   case IRQ_PMC1D_PMC2A:   case IRQ_LM_SIG_0:
187                case IRQ_LM_SIG_1:      case IRQ_TIMER_0:       case IRQ_TIMER_1:
188                case IRQ_TIMER_2:       case IRQ_TIMER_3:       case IRQ_IPI_0:
189                case IRQ_IPI_1:         case IRQ_IPI_2:         case IRQ_IPI_3:
190                case IRQ_RAVEN_ERROR:
191            *old_isr_handler = handlers[vector];
192            handlers[vector] = new_isr_handler;
193            return RTEMS_SUCCESSFUL;
194        default:
195            return RTEMS_INVALID_NUMBER;
196    }
197}
198
199#define PIC1_Mask (*(unsigned8 *) IO_TO_LOCAL(0x21))
200#define PIC2_Mask  (*(unsigned8 *) IO_TO_LOCAL(0xA1))
201
202
203rtems_status_code bsp_interrupt_enable(rtems_vector_number vector,
204                                       int priority) {
205    switch (vector) {
206                case IRQ_ISA_TIMER:     case IRQ_UART:          case IRQ_ISA_LM_SIG:
207                case IRQ_ABORT_SWITCH:  case IRQ_ISA_ETHERNET:  case IRQ_ISA_UNIVERSE:
208                case IRQ_ISA_PMC_PCIX:
209            if (priority != PRIORITY_ISA_INT) {
210                return RTEMS_INVALID_NUMBER;
211            }
212            if (vector < 8) {
213                PIC1_Mask &= ~ (1 << vector);
214            } else {
215                PIC2_Mask &= ~ (1 << (vector - 8));
216            }
217            return RTEMS_SUCCESSFUL;
218
219                case IRQ_ETHERNET:     case IRQ_VME_LINT0:    case IRQ_VME_LINT1:
220                case IRQ_VME_LINT2:    case IRQ_VME_LINT3:    case IRQ_PMC1A_PMC2B:
221                case IRQ_PMC1B_PMC2C:  case IRQ_PMC1C_PMC2D:  case IRQ_PMC1D_PMC2A:
222                case IRQ_LM_SIG_0:     case IRQ_LM_SIG_1:
223            if (priority & ~15) {
224                return RTEMS_INVALID_NUMBER;
225            }
226            st_le32(vec_prio_reg_addresses[vector],
227                    0x00400000 | (priority << 16) | vector);
228            return RTEMS_SUCCESSFUL;
229
230                case IRQ_FALCON_ECC:  case IRQ_TIMER_0:  case IRQ_TIMER_1:
231                case IRQ_TIMER_2:     case IRQ_TIMER_3:  case IRQ_IPI_0:
232                case IRQ_IPI_1:       case IRQ_IPI_2:    case IRQ_IPI_3:
233                case IRQ_RAVEN_ERROR:
234            if (priority & ~15) {
235                return RTEMS_INVALID_NUMBER;
236            }
237            st_le32(vec_prio_reg_addresses[vector], (priority << 16) | vector);
238            return RTEMS_SUCCESSFUL;
239
240        default:
241            return RTEMS_INVALID_NUMBER;
242    }
243}
244
245rtems_status_code bsp_interrupt_disable(rtems_vector_number vector) {
246    switch (vector) {
247                case IRQ_ISA_TIMER:     case IRQ_UART:          case IRQ_ISA_LM_SIG:
248                case IRQ_ABORT_SWITCH:  case IRQ_ISA_ETHERNET:  case IRQ_ISA_UNIVERSE:
249                case IRQ_ISA_PMC_PCIX:
250            if (vector < 8) {
251                PIC1_Mask |= (1 << vector);
252            } else {
253                PIC2_Mask |= (1 << (vector - 8));
254            }
255            return RTEMS_SUCCESSFUL;
256
257                case IRQ_FALCON_ECC:   case IRQ_ETHERNET:     case IRQ_VME_LINT0:
258                case IRQ_VME_LINT1:    case IRQ_VME_LINT2:    case IRQ_VME_LINT3:
259                case IRQ_PMC1A_PMC2B:  case IRQ_PMC1B_PMC2C:  case IRQ_PMC1C_PMC2D:
260                case IRQ_PMC1D_PMC2A:  case IRQ_LM_SIG_0:     case IRQ_LM_SIG_1:
261                case IRQ_TIMER_0:      case IRQ_TIMER_1:      case IRQ_TIMER_2:
262                case IRQ_TIMER_3:      case IRQ_IPI_0:        case IRQ_IPI_1:
263                case IRQ_IPI_2:        case IRQ_IPI_3:        case IRQ_RAVEN_ERROR:
264            st_le32(vec_prio_reg_addresses[vector], DISABLE_IRQ | vector);
265            return RTEMS_SUCCESSFUL;
266
267        default:
268            return RTEMS_INVALID_NUMBER;
269    }
270}
271
272rtems_status_code bsp_start_timer(int timer, int period_usec) {
273    double counts = (double)period_usec * timer_frequency / 1.0e6 + 0.5;
274    if (counts < 1.0 || counts > (double)0x7fffffff) {
275        return RTEMS_INVALID_NUMBER;
276    }
277    switch (timer) {
278        case 0:
279            st_le32(raven_base + 0x01110, (int)counts);
280            break;
281        case 1:
282            st_le32(raven_base + 0x01150, (int)counts);
283            break;
284        case 2:
285            st_le32(raven_base + 0x01190, (int)counts);
286            break;
287        case 3:
288            st_le32(raven_base + 0x011d0, (int)counts);
289            break;
290        default:
291            return RTEMS_INVALID_NUMBER;
292    }
293    return RTEMS_SUCCESSFUL;
294}
295
296rtems_status_code bsp_stop_timer(int timer) {
297    switch (timer) {
298        case 0:
299            st_le32(raven_base + 0x01110, 0x80000000);
300            break;
301        case 1:
302            st_le32(raven_base + 0x01150, 0x80000000);
303            break;
304        case 2:
305            st_le32(raven_base + 0x01190, 0x80000000);
306            break;
307        case 3:
308            st_le32(raven_base + 0x011d0, 0x80000000);
309            break;
310        default:
311            return RTEMS_INVALID_NUMBER;
312    }
313    return RTEMS_SUCCESSFUL;
314}
315
316rtems_status_code bsp_read_timer(int timer, int *value) {
317    switch (timer) {
318        case 0:
319            *value = ld_le32(raven_base + 0x01100) & 0x7fffffff;
320            break;
321        case 1:
322            *value = ld_le32(raven_base + 0x01140) & 0x7fffffff;
323            break;
324        case 2:
325            *value = ld_le32(raven_base + 0x01180) & 0x7fffffff;
326            break;
327        case 3:
328            *value = ld_le32(raven_base + 0x011c0) & 0x7fffffff;
329            break;
330        default:
331            return RTEMS_INVALID_NUMBER;
332    }
333    return RTEMS_SUCCESSFUL;
334}
335
336rtems_status_code generate_interprocessor_interrupt(int interrupt) {
337    int *dispatch_reg = raven_base + 0x20040;
338
339    if (interrupt & ~3) {
340        return RTEMS_INVALID_NUMBER;
341    }
342    dispatch_reg[interrupt << 2] = 1;
343    return RTEMS_SUCCESSFUL;
344}
345
346rtems_status_code set_interrupt_task_priority(int priority) {
347    if (priority & ~15) {
348        return RTEMS_INVALID_NUMBER;
349    }
350    st_le32(raven_base + 0x20080, priority);
351    return RTEMS_SUCCESSFUL;
352}
353
Note: See TracBrowser for help on using the repository browser.