1use kernel::utilities::StaticRef;
8use kernel::utilities::registers::interfaces::{Readable, Writeable};
9use kernel::utilities::registers::{
10 ReadOnly, ReadWrite, WriteOnly, register_bitfields, register_structs,
11};
12
13register_structs! {
14 BpmRegisters {
15 (0x000 => ier: WriteOnly<u32, Interrupt::Register>),
16 (0x004 => idr: WriteOnly<u32, Interrupt::Register>),
17 (0x008 => imr: ReadOnly<u32, Interrupt::Register>),
18 (0x00C => isr: ReadOnly<u32, Interrupt::Register>),
19 (0x010 => icr: WriteOnly<u32, Interrupt::Register>),
20 (0x014 => sr: ReadOnly<u32, Status::Register>),
21 (0x018 => unlock: ReadWrite<u32, Unlock::Register>),
22 (0x01C => pmcon: ReadWrite<u32, PowerModeControl::Register>),
23 (0x020 => _reserved0: [u32; 2]),
24 (0x028 => bkupwcause: ReadOnly<u32, BackupWakeup::Register>),
25 (0x02C => bkupwen: ReadWrite<u32, BackupWakeup::Register>),
26 (0x030 => bkuppmux: ReadWrite<u32, BackupPinMuxing::Register>),
27 (0x034 => ioret: ReadWrite<u32, InputOutputRetention::Register>),
28 (0x038 => @END),
29 }
30}
31
32register_bitfields![u32,
33 Interrupt [
34 AE 31,
36 PSOK 0
38 ],
39
40 Status [
41 AE 31,
43 PSOK 0
45 ],
46
47 Unlock [
48 KEY OFFSET(24) NUMBITS(8) [],
50 ADDR OFFSET(0) NUMBITS(10) []
52 ],
53
54 PowerModeControl [
55 FASTWKUP OFFSET(24) NUMBITS(1) [
57 NormalWakeup = 0,
58 FastWakeup = 1
59 ],
60 CK32S OFFSET(16) NUMBITS(1) [
62 Osc32k = 0,
63 Rc32k = 1
64 ],
65 SLEEP OFFSET(12) NUMBITS(2) [
67 CpuStopped = 0,
68 CpuAhbStopped = 1,
69 CpuAhbPbGclkStopped = 2,
70 CpuAhbPbGclkClockStopped = 3
71 ],
72 RET OFFSET(9) NUMBITS(1) [
74 NoPowerSave = 0,
75 PowerSave = 1
76 ],
77 BKUP OFFSET(8) NUMBITS(1) [
79 NoPowerSave = 0,
80 PowerSave = 1
81 ],
82 PSCM OFFSET(3) NUMBITS(1) [
91 WithCpuHalt = 0,
92 WithoutCpuHalt = 1
93 ],
94 PSCREQ OFFSET(2) NUMBITS(1) [
96 PowerScalingNotRequested = 0,
97 PowerScalingRequested = 1
98 ],
99 PS OFFSET(0) NUMBITS(2) []
101 ],
102
103 BackupWakeup [
104 BKUP OFFSET(0) NUMBITS(32) [
105 Eic = 0b000001,
106 Ast = 0b000010,
107 Wdt = 0b000100,
108 Bod33 = 0b001000,
109 Bod18 = 0b010000,
110 Picouart = 0b100000
111 ]
112 ],
113
114 BackupPinMuxing [
115 BKUPPMUX OFFSET(0) NUMBITS(9) [
117 Pb01 = 0b000000001,
118 Pa06 = 0b000000010,
119 Pa04 = 0b000000100,
120 Pa05 = 0b000001000,
121 Pa07 = 0b000010000,
122 Pc03 = 0b000100000,
123 Pc04 = 0b001000000,
124 Pc05 = 0b010000000,
125 Pc06 = 0b100000000
126 ]
127 ],
128
129 InputOutputRetention [
130 RET OFFSET(0) NUMBITS(1) [
132 IoLinesNotHeld = 0,
133 IoLinesHeld = 1
134 ]
135 ]
136];
137
138const BPM_UNLOCK_KEY: u32 = 0xAA;
139
140const BPM: StaticRef<BpmRegisters> = unsafe { StaticRef::new(0x400F0000 as *const BpmRegisters) };
141
142pub enum PowerScaling {
147 PS0,
152
153 PS1,
163
164 PS2,
169}
170
171pub enum CK32Source {
172 OSC32K = 0,
173 RC32K = 1,
174}
175
176#[inline(never)]
177pub unsafe fn set_ck32source(source: CK32Source) {
178 let control = BPM.pmcon.extract();
179 unlock_register(0x1c); BPM.pmcon
181 .modify_no_read(control, PowerModeControl::CK32S.val(source as u32));
182}
183
184unsafe fn unlock_register(register_offset: u32) {
185 BPM.unlock
186 .write(Unlock::KEY.val(BPM_UNLOCK_KEY) + Unlock::ADDR.val(register_offset));
187}
188
189unsafe fn power_scaling_ok() -> bool {
190 BPM.sr.is_set(Status::PSOK)
191}
192
193pub unsafe fn set_power_scaling(ps_value: PowerScaling) {
195 while !power_scaling_ok() {}
198
199 let control = BPM.pmcon.extract();
200
201 unlock_register(0x1c); BPM.pmcon.modify_no_read(
206 control,
207 PowerModeControl::PS.val(ps_value as u32)
208 + PowerModeControl::PSCM::WithoutCpuHalt
209 + PowerModeControl::PSCREQ::PowerScalingRequested,
210 );
211}