1 | /** |
---|
2 | * @file |
---|
3 | * |
---|
4 | * @ingroup bsp_interrupt |
---|
5 | * @ingroup arm_beagle |
---|
6 | * |
---|
7 | * @brief Interrupt support. |
---|
8 | */ |
---|
9 | |
---|
10 | /* |
---|
11 | * Copyright (c) 2014 Ben Gras <beng@shrike-systems.com>. All rights reserved. |
---|
12 | * |
---|
13 | * The license and distribution terms for this file may be |
---|
14 | * found in the file LICENSE in this distribution or at |
---|
15 | * http://www.rtems.org/license/LICENSE. |
---|
16 | */ |
---|
17 | |
---|
18 | #include <bsp.h> |
---|
19 | #include <bsp/irq-generic.h> |
---|
20 | #include <bsp/linker-symbols.h> |
---|
21 | |
---|
22 | #include <rtems/score/armv4.h> |
---|
23 | |
---|
24 | #include <libcpu/arm-cp15.h> |
---|
25 | |
---|
26 | struct omap_intr |
---|
27 | { |
---|
28 | uint32_t base; |
---|
29 | int size; |
---|
30 | }; |
---|
31 | |
---|
32 | #if IS_DM3730 |
---|
33 | static struct omap_intr omap_intr = { |
---|
34 | .base = OMAP3_DM37XX_INTR_BASE, |
---|
35 | .size = 0x1000, |
---|
36 | }; |
---|
37 | #endif |
---|
38 | |
---|
39 | #if IS_AM335X |
---|
40 | static struct omap_intr omap_intr = { |
---|
41 | .base = OMAP3_AM335X_INTR_BASE, |
---|
42 | .size = 0x1000, |
---|
43 | }; |
---|
44 | #endif |
---|
45 | |
---|
46 | static int irqs_enabled[BSP_INTERRUPT_VECTOR_MAX+1]; |
---|
47 | |
---|
48 | volatile static int level = 0; |
---|
49 | |
---|
50 | void bsp_interrupt_dispatch(void) |
---|
51 | { |
---|
52 | /* get irq */ |
---|
53 | uint32_t reg = mmio_read(omap_intr.base + OMAP3_INTCPS_SIR_IRQ); |
---|
54 | int irq; |
---|
55 | irq = reg & OMAP3_INTR_ACTIVEIRQ_MASK; |
---|
56 | |
---|
57 | if(!irqs_enabled[irq]) { |
---|
58 | /* Ignore spurious interrupt */ |
---|
59 | } else { |
---|
60 | bsp_interrupt_vector_disable(irq); |
---|
61 | |
---|
62 | /* enable new interrupts, and flush data cache to make sure |
---|
63 | * it hits the intc |
---|
64 | */ |
---|
65 | mmio_write(omap_intr.base + OMAP3_INTCPS_CONTROL, OMAP3_INTR_NEWIRQAGR); |
---|
66 | flush_data_cache(); |
---|
67 | mmio_read(omap_intr.base + OMAP3_INTCPS_SIR_IRQ); |
---|
68 | flush_data_cache(); |
---|
69 | |
---|
70 | /* keep current irq masked but enable unmasked ones */ |
---|
71 | uint32_t psr = _ARMV4_Status_irq_enable(); |
---|
72 | bsp_interrupt_handler_dispatch(irq); |
---|
73 | |
---|
74 | _ARMV4_Status_restore(psr); |
---|
75 | |
---|
76 | bsp_interrupt_vector_enable(irq); |
---|
77 | } |
---|
78 | } |
---|
79 | |
---|
80 | static uint32_t get_mir_reg(int vector, uint32_t *mask) |
---|
81 | { |
---|
82 | *mask = 1UL << (vector % 32); |
---|
83 | |
---|
84 | if(vector < 0) while(1) ; |
---|
85 | if(vector < 32) return OMAP3_INTCPS_MIR0; |
---|
86 | if(vector < 64) return OMAP3_INTCPS_MIR1; |
---|
87 | if(vector < 96) return OMAP3_INTCPS_MIR2; |
---|
88 | if(vector < 128) return OMAP3_INTCPS_MIR3; |
---|
89 | while(1) ; |
---|
90 | } |
---|
91 | |
---|
92 | rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector) |
---|
93 | { |
---|
94 | uint32_t mask, cur; |
---|
95 | uint32_t mir_reg = get_mir_reg(vector, &mask); |
---|
96 | |
---|
97 | cur = mmio_read(omap_intr.base + mir_reg); |
---|
98 | mmio_write(omap_intr.base + mir_reg, cur & ~mask); |
---|
99 | flush_data_cache(); |
---|
100 | |
---|
101 | irqs_enabled[vector] = 1; |
---|
102 | |
---|
103 | return RTEMS_SUCCESSFUL; |
---|
104 | } |
---|
105 | |
---|
106 | rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector) |
---|
107 | { |
---|
108 | uint32_t mask, cur; |
---|
109 | uint32_t mir_reg = get_mir_reg(vector, &mask); |
---|
110 | |
---|
111 | cur = mmio_read(omap_intr.base + mir_reg); |
---|
112 | mmio_write(omap_intr.base + mir_reg, cur | mask); |
---|
113 | flush_data_cache(); |
---|
114 | |
---|
115 | irqs_enabled[vector] = 0; |
---|
116 | |
---|
117 | return RTEMS_SUCCESSFUL; |
---|
118 | } |
---|
119 | |
---|
120 | rtems_status_code bsp_interrupt_facility_initialize(void) |
---|
121 | { |
---|
122 | int i; |
---|
123 | uint32_t intc_ilrx; |
---|
124 | |
---|
125 | /* AM335X TRM 6.2.1 Initialization Sequence */ |
---|
126 | mmio_write(omap_intr.base + OMAP3_INTCPS_SYSCONFIG, OMAP3_SYSCONFIG_AUTOIDLE); |
---|
127 | mmio_write(omap_intr.base + OMAP3_INTCPS_IDLE, 0); |
---|
128 | /* priority 0 to all IRQs */ |
---|
129 | for(intc_ilrx = 0x100; intc_ilrx <= 0x2fc; intc_ilrx += 4) { |
---|
130 | mmio_write(omap_intr.base + intc_ilrx, 0); |
---|
131 | } |
---|
132 | |
---|
133 | /* Mask all interrupts */ |
---|
134 | for(i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; i++) |
---|
135 | bsp_interrupt_vector_disable(i); |
---|
136 | |
---|
137 | /* Install generic interrupt handler */ |
---|
138 | arm_cp15_set_exception_handler(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt); |
---|
139 | arm_cp15_set_vector_base_address(bsp_vector_table_begin); |
---|
140 | |
---|
141 | return RTEMS_SUCCESSFUL; |
---|
142 | } |
---|