xref: /haiku/src/system/kernel/arch/arm/soc_sun4i.cpp (revision 02463fb461904c264e5d559f6ec1de92cf35e436)
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