1use kernel::utilities::registers::interfaces::{Readable, Writeable};
8use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite, WriteOnly};
9use kernel::utilities::StaticRef;
10
11#[repr(C)]
12struct BpmRegisters {
13 ier: WriteOnly<u32, Interrupt::Register>,
14 idr: WriteOnly<u32, Interrupt::Register>,
15 imr: ReadOnly<u32, Interrupt::Register>,
16 isr: ReadOnly<u32, Interrupt::Register>,
17 icr: WriteOnly<u32, Interrupt::Register>,
18 sr: ReadOnly<u32, Status::Register>,
19 unlock: ReadWrite<u32, Unlock::Register>,
20 pmcon: ReadWrite<u32, PowerModeControl::Register>,
21 _reserved0: [u32; 2],
22 bkupwcause: ReadOnly<u32, BackupWakeup::Register>,
23 bkupwen: ReadWrite<u32, BackupWakeup::Register>,
24 bkuppmux: ReadWrite<u32, BackupPinMuxing::Register>,
25 ioret: ReadWrite<u32, InputOutputRetention::Register>,
26}
27
28register_bitfields![u32,
29 Interrupt [
30 AE 31,
32 PSOK 0
34 ],
35
36 Status [
37 AE 31,
39 PSOK 0
41 ],
42
43 Unlock [
44 KEY OFFSET(24) NUMBITS(8) [],
46 ADDR OFFSET(0) NUMBITS(10) []
48 ],
49
50 PowerModeControl [
51 FASTWKUP OFFSET(24) NUMBITS(1) [
53 NormalWakeup = 0,
54 FastWakeup = 1
55 ],
56 CK32S OFFSET(16) NUMBITS(1) [
58 Osc32k = 0,
59 Rc32k = 1
60 ],
61 SLEEP OFFSET(12) NUMBITS(2) [
63 CpuStopped = 0,
64 CpuAhbStopped = 1,
65 CpuAhbPbGclkStopped = 2,
66 CpuAhbPbGclkClockStopped = 3
67 ],
68 RET OFFSET(9) NUMBITS(1) [
70 NoPowerSave = 0,
71 PowerSave = 1
72 ],
73 BKUP OFFSET(8) NUMBITS(1) [
75 NoPowerSave = 0,
76 PowerSave = 1
77 ],
78 PSCM OFFSET(3) NUMBITS(1) [
87 WithCpuHalt = 0,
88 WithoutCpuHalt = 1
89 ],
90 PSCREQ OFFSET(2) NUMBITS(1) [
92 PowerScalingNotRequested = 0,
93 PowerScalingRequested = 1
94 ],
95 PS OFFSET(0) NUMBITS(2) []
97 ],
98
99 BackupWakeup [
100 BKUP OFFSET(0) NUMBITS(32) [
101 Eic = 0b000001,
102 Ast = 0b000010,
103 Wdt = 0b000100,
104 Bod33 = 0b001000,
105 Bod18 = 0b010000,
106 Picouart = 0b100000
107 ]
108 ],
109
110 BackupPinMuxing [
111 BKUPPMUX OFFSET(0) NUMBITS(9) [
113 Pb01 = 0b000000001,
114 Pa06 = 0b000000010,
115 Pa04 = 0b000000100,
116 Pa05 = 0b000001000,
117 Pa07 = 0b000010000,
118 Pc03 = 0b000100000,
119 Pc04 = 0b001000000,
120 Pc05 = 0b010000000,
121 Pc06 = 0b100000000
122 ]
123 ],
124
125 InputOutputRetention [
126 RET OFFSET(0) NUMBITS(1) [
128 IoLinesNotHeld = 0,
129 IoLinesHeld = 1
130 ]
131 ]
132];
133
134const BPM_UNLOCK_KEY: u32 = 0xAA;
135
136const BPM: StaticRef<BpmRegisters> = unsafe { StaticRef::new(0x400F0000 as *const BpmRegisters) };
137
138pub enum PowerScaling {
143 PS0,
148
149 PS1,
159
160 PS2,
165}
166
167pub enum CK32Source {
168 OSC32K = 0,
169 RC32K = 1,
170}
171
172#[inline(never)]
173pub unsafe fn set_ck32source(source: CK32Source) {
174 let control = BPM.pmcon.extract();
175 unlock_register(0x1c); BPM.pmcon
177 .modify_no_read(control, PowerModeControl::CK32S.val(source as u32));
178}
179
180unsafe fn unlock_register(register_offset: u32) {
181 BPM.unlock
182 .write(Unlock::KEY.val(BPM_UNLOCK_KEY) + Unlock::ADDR.val(register_offset));
183}
184
185unsafe fn power_scaling_ok() -> bool {
186 BPM.sr.is_set(Status::PSOK)
187}
188
189pub unsafe fn set_power_scaling(ps_value: PowerScaling) {
191 while !power_scaling_ok() {}
194
195 let control = BPM.pmcon.extract();
196
197 unlock_register(0x1c); BPM.pmcon.modify_no_read(
202 control,
203 PowerModeControl::PS.val(ps_value as u32)
204 + PowerModeControl::PSCM::WithoutCpuHalt
205 + PowerModeControl::PSCREQ::PowerScalingRequested,
206 );
207}