1 /*
2 * Copyright 2022, Adrien Destugues, pulkomandy@pulkomandy.tk
3 * Distributed under the terms of the MIT License.
4 */
5
6 #include <vm/vm.h>
7
8 #include "soc_sun4i.h"
9
10
11 #define SUN4I_INTC_PEND_REG0 0x10
12 #define SUN4I_INTC_PEND_REG1 0x14
13 #define SUN4I_INTC_PEND_REG2 0x18
14 #define SUN4I_INTC_MASK_REG0 0x50
15 #define SUN4I_INTC_MASK_REG1 0x54
16 #define SUN4I_INTC_MASK_REG2 0x58
17
18
19 void
EnableInterrupt(int32 irq)20 Sun4iInterruptController::EnableInterrupt(int32 irq)
21 {
22 if (irq <= 31) {
23 fRegBase[SUN4I_INTC_MASK_REG0] |= 1 << irq;
24 return;
25 }
26
27 if (irq <= 63) {
28 fRegBase[SUN4I_INTC_MASK_REG1] |= 1 << (irq - 32);
29 return;
30 }
31
32 fRegBase[SUN4I_INTC_MASK_REG2] |= 1 << (irq - 64);
33 }
34
35
36 void
DisableInterrupt(int irq)37 Sun4iInterruptController::DisableInterrupt(int irq)
38 {
39 if (irq <= 31) {
40 fRegBase[SUN4I_INTC_MASK_REG0] &= ~(1 << irq);
41 return;
42 }
43
44 if (irq <= 63) {
45 fRegBase[SUN4I_INTC_MASK_REG1] &= ~(1 << (irq - 32));
46 return;
47 }
48
49 fRegBase[SUN4I_INTC_MASK_REG1] &= ~(1 << (irq - 64));
50 }
51
52
53 void
HandleInterrupt()54 Sun4iInterruptController::HandleInterrupt()
55 {
56 // FIXME can we use the hardware managed interrupt vector instead?
57 for (int i=0; i < 32; i++) {
58 if (fRegBase[SUN4I_INTC_PEND_REG0] & (1 << i))
59 int_io_interrupt_handler(i, true);
60 }
61
62 for (int i=0; i < 32; i++) {
63 if (fRegBase[SUN4I_INTC_PEND_REG1] & (1 << i))
64 int_io_interrupt_handler(i + 32, true);
65 }
66
67 for (int i=0; i < 32; i++) {
68 if (fRegBase[SUN4I_INTC_PEND_REG2] & (1 << i))
69 int_io_interrupt_handler(i + 64, true);
70 }
71 }
72
73
Sun4iInterruptController(uint32_t reg_base)74 Sun4iInterruptController::Sun4iInterruptController(uint32_t reg_base)
75 {
76 fRegArea = vm_map_physical_memory(B_SYSTEM_TEAM, "intc-sun4i", (void**)&fRegBase,
77 B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
78 reg_base, false);
79 if (fRegArea < 0)
80 panic("Sun4iInterruptController: cannot map registers!");
81
82 fRegBase[SUN4I_INTC_MASK_REG0] = 0;
83 fRegBase[SUN4I_INTC_MASK_REG1] = 0;
84 fRegBase[SUN4I_INTC_MASK_REG2] = 0;
85 }
86