1 /*
2  * Copyright (c) 2015 Stefan Kristiansson
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #include <lk/err.h>
9 #include <lk/debug.h>
10 #include <kernel/thread.h>
11 #include <platform/interrupts.h>
12 #include <platform/pic.h>
13 #include <arch/or1k.h>
14 
15 static spin_lock_t gicd_lock;
16 #if WITH_LIB_SM
17 #define GICD_LOCK_FLAGS SPIN_LOCK_FLAG_IRQ_FIQ
18 #else
19 #define GICD_LOCK_FLAGS SPIN_LOCK_FLAG_INTERRUPTS
20 #endif
21 
22 struct int_handler_struct {
23     int_handler handler;
24     void *arg;
25 };
26 
27 static struct int_handler_struct int_handler_table[MAX_INT];
28 
register_int_handler(unsigned int vector,int_handler handler,void * arg)29 void register_int_handler(unsigned int vector, int_handler handler, void *arg) {
30     spin_lock_saved_state_t state;
31 
32     if (vector >= MAX_INT)
33         panic("%s: vector out of range %d\n", __FUNCTION__, vector);
34 
35     spin_lock_save(&gicd_lock, &state, GICD_LOCK_FLAGS);
36 
37     int_handler_table[vector].handler = handler;
38     int_handler_table[vector].arg = arg;
39 
40     spin_unlock_restore(&gicd_lock, state, GICD_LOCK_FLAGS);
41 }
42 
mask_interrupt(unsigned int vector)43 status_t mask_interrupt(unsigned int vector) {
44     if (vector >= MAX_INT)
45         return ERR_INVALID_ARGS;
46 
47     mtspr(OR1K_SPR_PIC_PICMR_ADDR, mfspr(OR1K_SPR_PIC_PICMR_ADDR) & ~(1 << vector));
48 
49     return NO_ERROR;
50 }
51 
unmask_interrupt(unsigned int vector)52 status_t unmask_interrupt(unsigned int vector) {
53     if (vector >= MAX_INT)
54         return ERR_INVALID_ARGS;
55 
56     mtspr(OR1K_SPR_PIC_PICMR_ADDR, mfspr(OR1K_SPR_PIC_PICMR_ADDR) | (1 << vector));
57 
58     return NO_ERROR;
59 }
60 
platform_irq(void)61 enum handler_return platform_irq(void) {
62     enum handler_return ret = INT_NO_RESCHEDULE;
63 
64     uint irq = __builtin_ffs(mfspr(OR1K_SPR_PIC_PICSR_ADDR)) - 1;
65 
66     if (irq < MAX_INT && int_handler_table[irq].handler)
67         ret = int_handler_table[irq].handler(int_handler_table[irq].arg);
68 
69     return ret;
70 }
71