1use kernel::platform;
8use kernel::utilities::registers::interfaces::{Readable, Writeable};
9use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite, WriteOnly};
10use kernel::utilities::StaticRef;
11
12register_structs! {
15 pub AonTimerRegisters {
16 (0x000 => alert_test: WriteOnly<u32, ALERT_TEST::Register>),
18 (0x004 => wkup_ctrl: ReadWrite<u32, WKUP_CTRL::Register>),
20 (0x008 => wkup_thold: ReadWrite<u32, THRESHOLD::Register>),
22 (0x00C => wkup_count: ReadWrite<u32, WKUP_COUNT::Register>),
24 (0x010 => wdog_regwen: ReadWrite<u32, WDOG_REGWEN::Register>),
26 (0x014 => wdog_ctrl: ReadWrite<u32, WDOG_CTRL::Register>),
28 (0x018 => wdog_bark_thold: ReadWrite<u32, THRESHOLD::Register>),
30 (0x01C => wdog_bite_thold: ReadWrite<u32, THRESHOLD::Register>),
32 (0x020 => wdog_count: ReadWrite<u32, WDOG_COUNT::Register>),
34 (0x024 => intr_state: ReadWrite<u32, INTR::Register>),
36 (0x028 => intr_test: WriteOnly<u32, INTR::Register>),
38 (0x02C => wkup_cause: ReadWrite<u32, WKUP_CAUSE::Register>),
40 (0x030 => @END),
41 }
42}
43
44register_bitfields![u32,
45 ALERT_TEST[
46 FATAL_FAULT OFFSET(0) NUMBITS(1) []
47 ],
48 WKUP_CTRL[
49 ENABLE OFFSET(0) NUMBITS(1) [],
50 PRESCALER OFFSET(1) NUMBITS(12) []
51 ],
52 THRESHOLD[
53 THRESHOLD OFFSET(0) NUMBITS(32) []
54 ],
55 WKUP_COUNT[
56 COUNT OFFSET(0) NUMBITS(32) []
57 ],
58 WDOG_REGWEN[
59 REGWEN OFFSET(0) NUMBITS(1) []
60 ],
61 WDOG_CTRL[
62 ENABLE OFFSET(0) NUMBITS(1) [],
63 PAUSE_IN_SLEEP OFFSET(1) NUMBITS(1) []
64 ],
65 WDOG_COUNT[
66 COUNT OFFSET(0) NUMBITS(32) [],
67 ],
68 INTR[
69 WKUP_TIMER_EXPIRED OFFSET(0) NUMBITS(1) [],
70 WDOG_TIMER_BARK OFFSET(1) NUMBITS(1) []
71 ],
72 WKUP_CAUSE[
73 CAUSE OFFSET(0) NUMBITS(1) [],
74 ]
75];
76
77pub struct AonTimer {
78 registers: StaticRef<AonTimerRegisters>,
79 aon_clk_freq: u32, }
81
82impl AonTimer {
83 pub const fn new(base: StaticRef<AonTimerRegisters>, aon_clk_freq: u32) -> AonTimer {
84 AonTimer {
85 registers: base,
86 aon_clk_freq,
87 }
88 }
89
90 fn reset_timers(&self) {
92 let regs = self.registers;
93 regs.wkup_count.set(0x00);
94 regs.wdog_count.set(0x00);
95 }
96
97 fn wdog_start_count(&self) {
100 self.registers
101 .wdog_ctrl
102 .write(WDOG_CTRL::ENABLE::SET + WDOG_CTRL::PAUSE_IN_SLEEP::SET);
103 }
104
105 fn set_wdog_thresh(&self) {
107 let regs = self.registers;
108 let bark_cycles = self.ms_to_cycles(500);
112 let bite_cycles = bark_cycles.saturating_mul(2);
114
115 regs.wdog_bark_thold
116 .write(THRESHOLD::THRESHOLD.val(bark_cycles));
117 regs.wdog_bite_thold
118 .write(THRESHOLD::THRESHOLD.val(bite_cycles));
119 }
120
121 fn wdog_pet(&self) {
123 self.registers.wdog_count.set(0x00);
124 }
125
126 fn wdog_suspend(&self) {
127 self.registers.wdog_ctrl.write(WDOG_CTRL::ENABLE::CLEAR);
128 }
129
130 fn wdog_resume(&self) {
131 self.registers.wdog_ctrl.write(WDOG_CTRL::ENABLE::SET);
132 }
133
134 fn lock_wdog_conf(&self) {
136 self.registers.wdog_regwen.write(WDOG_REGWEN::REGWEN::SET)
137 }
138
139 fn ms_to_cycles(&self, ms: u32) -> u32 {
141 ms.saturating_mul(self.aon_clk_freq).saturating_div(1000)
143 }
144
145 fn reset_wkup_count(&self) {
146 self.registers.wkup_count.set(0x00);
147 }
148
149 pub fn handle_interrupt(&self) {
150 let regs = self.registers;
151 let intr = self.registers.intr_state.extract();
152
153 if intr.is_set(INTR::WKUP_TIMER_EXPIRED) {
154 regs.wkup_cause.set(0x00);
156 regs.wkup_count.set(0x00); self.reset_wkup_count();
158 regs.intr_state.write(INTR::WKUP_TIMER_EXPIRED::SET);
160 }
161
162 if intr.is_set(INTR::WDOG_TIMER_BARK) {
163 regs.intr_state.write(INTR::WDOG_TIMER_BARK::SET);
165 self.wdog_pet();
166 }
167 }
168}
169
170impl platform::watchdog::WatchDog for AonTimer {
171 fn setup(&self) {
180 self.reset_timers();
182
183 self.set_wdog_thresh();
185
186 self.wdog_start_count();
188
189 self.lock_wdog_conf();
193 }
194
195 fn tickle(&self) {
196 self.wdog_pet();
198 }
199
200 fn suspend(&self) {
201 self.wdog_suspend();
202 }
203
204 fn resume(&self) {
205 self.wdog_resume();
206 }
207}