a bit more work on the systimer interrupt
[AROS.git] / arch / arm-raspi / kernel / intr.c
blob38cae97259ec0540f8118c583196d942f7c66b8d
1 /*
2 Copyright © 2013, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 1
8 #include <inttypes.h>
9 #include <aros/kernel.h>
10 #include <aros/libcall.h>
11 #include <hardware/intbits.h>
12 #include <stddef.h>
13 #include <string.h>
15 #include <proto/exec.h>
16 #include <proto/kernel.h>
18 #include "kernel_intern.h"
19 #include "kernel_debug.h"
20 #include "kernel_interrupts.h"
22 extern void core_Cause(unsigned char, unsigned int);
24 #define IRQBANK_POINTER(bank) ((bank == 0) ? GPUIRQ_ENBL0 : (bank == 1) ? GPUIRQ_ENBL1 : ARMIRQ_ENBL)
26 #define DREGS(x) x
28 void ictl_enable_irq(uint8_t irq, struct KernelBase *KernelBase)
30 int bank = IRQ_BANK(irq);
31 unsigned int val, reg;
33 reg = IRQBANK_POINTER(bank);
35 D(bug("[KRN] Enabling irq %d [bank %d, reg 0x%p]\n", irq, bank, reg));
36 val = *((volatile unsigned int *)reg);
37 val |= IRQ_MASK(irq);
38 *((volatile unsigned int *)reg) = val;
41 void ictl_disable_irq(uint8_t irq, struct KernelBase *KernelBase)
43 int bank = IRQ_BANK(irq);
44 unsigned int val, reg;
46 reg = IRQBANK_POINTER(bank);
48 D(bug("[KRN] Dissabling irq %d [bank %d, reg 0x%p]\n", irq, bank, reg));
50 val = *((volatile unsigned int *)reg);
51 val |= IRQ_MASK(irq);
52 *((volatile unsigned int *)reg) = val;
55 void __intrhand_undef(void)
57 register unsigned int addr;
59 *gpioGPSET0 = 1<<16; // LED OFF
61 asm volatile("mov %[addr], lr" : [addr] "=r" (addr) );
63 krnPanic(KernelBase, "CPU Unknown Instruction @ 0x%p", (addr - 4));
66 void __intrhand_reset(void)
68 *gpioGPSET0 = 1<<16; // LED OFF
70 D(bug("[KRN] ## RESET ##\n"));
71 while(1)
73 asm("mov r0,r0\n\t");
75 return;
78 /** SWI handled in syscall.c */
80 asm (".globl __intrhand_irq\n\t"
81 ".type __intrhand_irq,%function\n"
82 "__intrhand_irq:\n"
83 " sub lr, lr, #4 \n" // save return address and callers cpsr into system mode stack
84 " srsdb #0x1f! \n"
85 " cps #0x1f \n" // switch to system mode
86 " sub sp, sp, #3*4 \n" // make space to store callers lr, sp, and ip
87 " stmfd sp!, {r0-r11} \n" // store untouched registers to pass to c handler ..
88 " mov r0, sp \n" // r0 = registers r0-r12 on the stack
89 " str ip, [sp, #12*4] \n"
90 " add ip, sp, #16*4 \n" // store callers stack pointer ..
91 " str ip, [sp, #13*4] \n"
92 " str lr, [sp, #14*4] \n"
93 " ldr r1, [sp, #1*4] \n" // restore r1 ..
94 " ldr r2, [sp, #2*4] \n" // .. and r2 ..
95 " mov fp, #0 \n" // clear fp(??)
96 " bl handle_irq \n"
97 " ldr ip, [sp, #12*4] \n" // get task_ip
98 " ldr lr, [sp, #14*4] \n" // get task_lr
99 " ldr r2, [sp, #16*4] \n" // restore task_cpsr
100 " msr cpsr, r2 \n"
101 " ldmfd sp!, {r0-r11} \n" // restore remaining task_registers
102 " add sp, sp, #3*4 \n" // correct the stack pointer ..
103 " rfefd sp! \n" // ..and return
106 void handle_irq(void *regs)
108 struct ExceptionContext *ctx;
109 struct Task *thisTask;
110 unsigned int pending, processed, irq;
112 D(bug("[KRN] ## IRQ ##\n"));
114 if ((thisTask = SysBase->ThisTask) != NULL)
116 D(bug("[KRN] IRQ invoked in '%s'", thisTask->tc_Node.ln_Name));
117 if ((ctx = thisTask->tc_UnionETask.tc_ETask->et_RegFrame) != NULL)
119 int i;
121 D(bug(", ExceptionContext @ 0x%p", ctx));
122 DREGS(bug("\n"));
123 for (i = 0; i < 12; i++)
125 ctx->r[i] = ((uint32_t *)regs)[i];
126 DREGS(bug("[KRN] r%02d: 0x%08x\n", i, ctx->r[i]));
128 ctx->ip = ((uint32_t *)regs)[12];
129 DREGS(bug("[KRN] (ip) r12: 0x%08x\n", ctx->ip));
130 ctx->sp = ((uint32_t *)regs)[13];
131 DREGS(bug("[KRN] (sp) r13: 0x%08x\n", ctx->sp));
132 ctx->lr = ((uint32_t *)regs)[14];
133 DREGS(bug("[KRN] (lr) r14: 0x%08x\n", ctx->lr));
134 ctx->pc = ((uint32_t *)regs)[15];
135 DREGS(bug("[KRN] (pc) r15: 0x%08x\n", ctx->pc));
136 ctx->cpsr = ((uint32_t *)regs)[16];
137 DREGS(bug("[KRN] cpsr: 0x%08x", ctx->cpsr));
138 thisTask->tc_SPReg = ctx->sp;
140 D(bug("\n"));
143 pending = *((volatile unsigned int *)(GPUIRQ_PEND0));
144 irq = (0 << 5);
145 processed = 0;
146 while (pending != NULL)
148 if (pending & 1)
150 D(bug("[KRN] Handling IRQ %d ..\n", irq));
151 krnRunIRQHandlers(KernelBase, irq);
152 processed |= (1 << irq);
154 pending = pending >> 1;
155 irq++;
157 if (processed) *((volatile unsigned int *)(GPUIRQ_PEND0)) |= ~processed;
159 pending = *((volatile unsigned int *)(GPUIRQ_PEND1));
160 irq = (1 << 5);
161 processed = 0;
162 while (pending != NULL)
164 if (pending & 1)
166 D(bug("[KRN] Handling IRQ %d ..\n", irq));
167 krnRunIRQHandlers(KernelBase, irq);
168 processed |= (1 << irq);
170 pending = pending >> 1;
171 irq++;
173 if (processed) *((volatile unsigned int *)(GPUIRQ_PEND1)) |= ~processed;
175 pending = *((volatile unsigned int *)(ARMIRQ_PEND));
176 irq = (2 << 5);
177 processed = 0;
178 while (pending != NULL)
180 if (pending & 1)
182 D(bug("[KRN] Handling IRQ %d ..\n", irq));
183 krnRunIRQHandlers(KernelBase, irq);
184 processed |= (1 << irq);
186 pending = pending >> 1;
187 irq++;
189 if (processed) *((volatile unsigned int *)(ARMIRQ_PEND)) |= ~processed;
191 return;
194 __attribute__ ((interrupt ("FIQ"))) void __intrhand_fiq(void)
196 *gpioGPSET0 = 1<<16; // LED OFF
198 D(bug("[KRN] ## FIQ ##\n"));
199 while(1)
201 asm("mov r0,r0\n\t");
205 #ifndef RASPI_VIRTMEMSUPPORT
206 __attribute__ ((interrupt ("ABORT"))) void __intrhand_dataabort(void)
208 register unsigned int addr, far;
209 asm volatile("mov %[addr], lr" : [addr] "=r" (addr) );
210 /* Read fault address register */
211 asm volatile("mrc p15, 0, %[addr], c6, c0, 0": [addr] "=r" (far) );
213 *gpioGPSET0 = 1<<16; // LED OFF
215 /* Routine terminates by returning to LR-4, which is the instruction
216 * after the aborted one
217 * GCC doesn't properly deal with data aborts in its interrupt
218 * handling - no option to return to the failed instruction
220 krnPanic(KernelBase, "CPU Data Abort @ 0x%p, fault address: 0x%p", (addr - 4), far);
223 /* Return to this function after a prefetch abort */
224 __attribute__ ((interrupt ("ABORT"))) void __intrhand_prefetchabort(void)
226 register unsigned int addr;
227 asm volatile("mov %[addr], lr" : [addr] "=r" (addr) );
229 *gpioGPSET0 = 1<<16; // LED OFF
231 krnPanic(KernelBase, "CPU Prefetch Abort @ 0x%p", (addr - 4));
233 #else
234 #warning "TODO: Implement support for retrieving pages from medium, and reattempting access"
235 #endif
237 void GPUSysTimerHandler(unsigned int timerno, void *unused1)
239 D(bug("[KRN] GPUSysTimerHandler()\n"));
240 /* Signal the Exec VBlankServer */
241 if (SysBase && (SysBase->IDNestCnt < 0)) {
242 core_Cause(INTB_VERTB, 1L << INTB_VERTB);
246 /* linker exports */
247 extern void *__intvecs_start, *__intvecs_end;
249 void core_SetupIntr(void)
251 int irq;
252 bug("[KRN] Initializing cpu vectors\n");
254 /* Copy vectors into place */
255 memcpy(0, &__intvecs_start,
256 (unsigned int)&__intvecs_end -
257 (unsigned int)&__intvecs_start);
259 D(bug("[KRN] Copied %d bytes from 0x%p to 0x00000000\n", (unsigned int)&__intvecs_end - (unsigned int)&__intvecs_start, &__intvecs_start));
262 unsigned int x = 0;
263 bug("[KRN]: Vector dump-:");
264 for (x=0; x < (unsigned int)&__intvecs_end - (unsigned int)&__intvecs_start; x++) {
265 if ((x%16) == 0)
267 bug("\n[KRN]: %08x:", x);
269 bug(" %02x", *((volatile UBYTE *)x));
271 bug("\n");
274 D(bug("[KRN] Disabling IRQs\n"));
275 *(volatile ULONG *)ARMIRQ_DIBL = ~0;
276 *(volatile ULONG *)GPUIRQ_DIBL0 = ~0;
277 *(volatile ULONG *)GPUIRQ_DIBL1 = ~0;