summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/imx233/icoll-imx233.c50
1 files changed, 30 insertions, 20 deletions
diff --git a/firmware/target/arm/imx233/icoll-imx233.c b/firmware/target/arm/imx233/icoll-imx233.c
index e23af602db..4e3c6fe864 100644
--- a/firmware/target/arm/imx233/icoll-imx233.c
+++ b/firmware/target/arm/imx233/icoll-imx233.c
@@ -127,6 +127,15 @@ static isr_t isr_table[INT_SRC_COUNT] =
127static uint32_t irq_count_old[INT_SRC_COUNT]; 127static uint32_t irq_count_old[INT_SRC_COUNT];
128static uint32_t irq_count[INT_SRC_COUNT]; 128static uint32_t irq_count[INT_SRC_COUNT];
129 129
130unsigned imx233_icoll_get_priority(int src)
131{
132#if IMX233_SUBTARGET < 3780
133 return BF_RDn(ICOLL_PRIORITYn, src / 4, PRIORITYx(src % 4));
134#else
135 return BF_RDn(ICOLL_INTERRUPTn, src, PRIORITY);
136#endif
137}
138
130struct imx233_icoll_irq_info_t imx233_icoll_get_irq_info(int src) 139struct imx233_icoll_irq_info_t imx233_icoll_get_irq_info(int src)
131{ 140{
132 struct imx233_icoll_irq_info_t info; 141 struct imx233_icoll_irq_info_t info;
@@ -135,11 +144,7 @@ struct imx233_icoll_irq_info_t imx233_icoll_get_irq_info(int src)
135#else 144#else
136 info.enabled = BF_RDn(ICOLL_INTERRUPTn, src, ENABLE); 145 info.enabled = BF_RDn(ICOLL_INTERRUPTn, src, ENABLE);
137#endif 146#endif
138#if IMX233_SUBTARGET < 3780 147 info.priority = imx233_icoll_get_priority(src);
139 info.priority = BF_RDn(ICOLL_PRIORITYn, src / 4, PRIORITYx(src % 4));
140#else
141 info.priority = BF_RDn(ICOLL_INTERRUPTn, src, PRIORITY);
142#endif
143 info.freq = irq_count_old[src]; 148 info.freq = irq_count_old[src];
144 return info; 149 return info;
145} 150}
@@ -163,16 +168,23 @@ static void UIRQ(void)
163} 168}
164 169
165/* return the priority level */ 170/* return the priority level */
166int _irq_handler(uint32_t vec) 171void _irq_handler(void)
167{ 172{
173 /* read vector and notify as side effect */
174 uint32_t vec = HW_ICOLL_VECTOR;
168 int irq_nr = (vec - HW_ICOLL_VBASE) / 4; 175 int irq_nr = (vec - HW_ICOLL_VBASE) / 4;
176 /* check for IRQ storm */
169 if(irq_count[irq_nr]++ > IRQ_STORM_THRESHOLD) 177 if(irq_count[irq_nr]++ > IRQ_STORM_THRESHOLD)
170 panicf("IRQ %d: storm detected", irq_nr); 178 panicf("IRQ %d: storm detected", irq_nr);
179 /* do some regular stat */
171 if(irq_nr == INT_SRC_TIMER(TIMER_TICK)) 180 if(irq_nr == INT_SRC_TIMER(TIMER_TICK))
172 do_irq_stat(); 181 do_irq_stat();
182 /* enable interrupts again */
183 //enable_irq();
184 /* process interrupt */
173 (*(isr_t *)vec)(); 185 (*(isr_t *)vec)();
174 /* acknowledge completion of IRQ */ 186 /* acknowledge completion of IRQ */
175 return imx233_icoll_get_irq_info(irq_nr).priority; 187 HW_ICOLL_LEVELACK = 1 << imx233_icoll_get_priority(irq_nr);
176} 188}
177 189
178void irq_handler(void) 190void irq_handler(void)
@@ -181,22 +193,20 @@ void irq_handler(void)
181 asm volatile( 193 asm volatile(
182 "sub lr, lr, #4 \n" /* Create return address */ 194 "sub lr, lr, #4 \n" /* Create return address */
183 "stmfd sp!, { r0-r5, r12, lr } \n" /* Save what gets clobbered */ 195 "stmfd sp!, { r0-r5, r12, lr } \n" /* Save what gets clobbered */
184 "ldr r5, =0x8001c290 \n" /* Save pointer to instruction */ 196 "ldr r1, =0x8001c290 \n" /* Save pointer to instruction */
185 "str lr, [r5] \n" /* in HW_DIGCTL_SCRATCH0 */ 197 "str lr, [r1] \n" /* in HW_DIGCTL_SCRATCH0 */
186 "ldr r4, =0x80000000 \n" /* Read HW_ICOLL_VECTOR */
187 "ldr r0, [r4] \n" /* and notify as side-effect */
188 "mrs lr, spsr \n" /* Save SPSR_irq */ 198 "mrs lr, spsr \n" /* Save SPSR_irq */
189 "stmfd sp!, { lr } \n" /* Push it on the IRQ stack */ 199 "stmfd sp!, { r1, lr } \n" /* Push it on the stack */
190 "msr cpsr_c, #0x13 \n" /* Switch to SVC mode, enable IRQ */ 200 "msr cpsr_c, #0x93 \n" /* Switch to SVC mode, IRQ disabled */
191 "stmfd sp!, { lr } \n" /* Save lr_SVC */ 201 "mov r4, lr \n" /* Save lr_SVC */
192 "blx _irq_handler \n" /* Process IRQ, returns ack level */ 202 "and r5, sp, #4 \n" /* Align SVC stack */
193 "ldmfd sp!, { lr } \n" /* Restore lr_SVC */ 203 "sub sp, sp, r5 \n" /* on 8-byte boundary */
204 "blx _irq_handler \n" /* Process IRQ */
205 "add sp, sp, r5 \n" /* Undo alignement */
206 "mov lr, r4 \n" /* Restore lr_SVC */
194 "msr cpsr_c, #0x92 \n" /* Mask IRQ, return to IRQ mode */ 207 "msr cpsr_c, #0x92 \n" /* Mask IRQ, return to IRQ mode */
195 "ldmfd sp!, { lr } \n" /* Pop back SPSR */ 208 "ldmfd sp!, { r1, lr } \n" /* Reload saved value */
196 "msr spsr_cxsf, lr \n" /* Restore SPSR_irq */ 209 "msr spsr_cxsf, lr \n" /* Restore SPSR_irq */
197 "mov r3, #1 \n" /* Compute ack level value */
198 "lsl r0, r3, r0 \n" /* (1 << ack_lvl) */
199 "str r0, [r4, #0x10] \n" /* and write it to HW_ICOLL_LEVELACK */
200 "ldmfd sp!, { r0-r5, r12, pc }^ \n" /* Restore regs, and RFE */); 210 "ldmfd sp!, { r0-r5, r12, pc }^ \n" /* Restore regs, and RFE */);
201} 211}
202 212