1use crate::interrupts;
8use kernel::utilities::cells::VolatileCell;
9use kernel::utilities::registers::interfaces::{Readable, Writeable};
10use kernel::utilities::registers::{
11 register_bitfields, register_structs, LocalRegisterCopy, ReadWrite,
12};
13use kernel::utilities::StaticRef;
14
15register_structs! {
16 pub IntcRegisters {
17 (0x000 => _reserved0),
18 (0x040 => gpio_interrupt_pro_map: ReadWrite<u32>),
19 (0x044 => gpio_interrupt_pro_nmi_map: ReadWrite<u32>),
20 (0x048 => _reserved1),
21 (0x054 => uart0_intr_map: ReadWrite<u32>),
22 (0x058 => _reserved2),
23 (0x080 => timg0_intr_map: ReadWrite<u32>),
24 (0x084 => timg1_intr_map: ReadWrite<u32>),
25 (0x088 => _reserved3),
26 (0x0f8 => status: [ReadWrite<u32>; 2]),
27 (0x100 => clk_en: ReadWrite<u32>),
28 (0x104 => enable: ReadWrite<u32, INT::Register>),
29 (0x108 => type_reg: ReadWrite<u32, INT::Register>),
30 (0x10C => clear: ReadWrite<u32, INT::Register>),
31 (0x110 => eip: ReadWrite<u32, INT::Register>),
32 (0x114 => _reserved4),
33 (0x118 => priority: [ReadWrite<u32, PRIORITY::Register>; 31]),
34 (0x194 => thresh: ReadWrite<u32, THRESH::Register>),
35 (0x198 => @END),
36 }
37}
38
39register_bitfields![u32,
40 INT [
41 ONE OFFSET(1) NUMBITS(1) [],
42 TWO OFFSET(2) NUMBITS(1) [],
43 THREE OFFSET(3) NUMBITS(1) [],
44 FOUR OFFSET(4) NUMBITS(1) [],
45 FIVE OFFSET(5) NUMBITS(1) [],
46 SIX OFFSET(6) NUMBITS(1) [],
47 SEVEN OFFSET(7) NUMBITS(1) [],
48 EIGHT OFFSET(8) NUMBITS(1) [],
49 ],
50 PRIORITY [
51 PRIORITY OFFSET(0) NUMBITS(4) [],
52 ],
53 THRESH [
54 THRESH OFFSET(0) NUMBITS(4) [],
55 ],
56];
57
58pub struct Intc {
59 registers: StaticRef<IntcRegisters>,
60 saved: VolatileCell<LocalRegisterCopy<u32>>,
61}
62
63impl Intc {
64 pub const fn new(base: StaticRef<IntcRegisters>) -> Self {
65 Intc {
66 registers: base,
67 saved: VolatileCell::new(LocalRegisterCopy::new(0)),
68 }
69 }
70
71 pub fn map_interrupts(&self) {
77 self.registers.uart0_intr_map.set(interrupts::IRQ_UART0);
78 self.registers.timg0_intr_map.set(interrupts::IRQ_TIMER1);
79 self.registers.timg1_intr_map.set(interrupts::IRQ_TIMER2);
80 self.registers
81 .gpio_interrupt_pro_map
82 .set(interrupts::IRQ_GPIO);
83 self.registers
84 .gpio_interrupt_pro_nmi_map
85 .set(interrupts::IRQ_GPIO_NMI);
86 }
87
88 pub fn clear_all_pending(&self) {
90 self.registers.clear.set(0xFF);
91 }
92
93 pub fn enable_all(&self) {
95 self.registers.enable.set(0xFFFF_FFFF);
96
97 for priority in self.registers.priority.iter() {
100 priority.write(PRIORITY::PRIORITY.val(3));
101 }
102
103 self.registers.thresh.write(THRESH::THRESH.val(1));
105 }
106
107 pub fn disable(&self, irq: u32) {
109 let mask = !(1 << irq);
110 let value = self.registers.enable.get() & mask;
111 self.registers.enable.set(value);
112 }
113
114 pub fn disable_all(&self) {
116 self.registers.enable.set(0x00);
117 }
118
119 pub fn next_pending(&self) -> Option<u32> {
123 let eip = self.registers.eip.get();
124 if eip == 0 {
125 None
126 } else {
127 Some(eip.trailing_zeros())
128 }
129 }
130
131 pub unsafe fn save_interrupt(&self, irq: u32) {
137 let new_saved = self.saved.get().get() | 1 << irq;
139
140 self.saved.set(LocalRegisterCopy::new(new_saved));
142 }
143
144 pub fn get_saved_interrupts(&self) -> Option<u32> {
148 let saved = self.saved.get().get();
149 if saved != 0 {
150 return Some(saved.trailing_zeros());
151 }
152
153 None
154 }
155
156 pub unsafe fn complete(&self, irq: u32) {
160 let new_saved = self.saved.get().get() & !(1 << irq);
162
163 self.saved.set(LocalRegisterCopy::new(new_saved));
165 }
166}