1use crate::bpm;
8use crate::bscif;
9use crate::flashcalw;
10use crate::gpio;
11use crate::scif;
12use core::cell::Cell;
13use core::sync::atomic::Ordering;
14use kernel::platform::chip::ClockInterface;
15use kernel::utilities::StaticRef;
16use kernel::utilities::registers::interfaces::{Readable, Writeable};
17use kernel::utilities::registers::{
18 FieldValue, ReadOnly, ReadWrite, WriteOnly, register_bitfields, register_structs,
19};
20
21register_structs! {
22 PmRegisters {
24 (0x000 => mcctrl: ReadWrite<u32, MainClockControl::Register>),
25 (0x004 => cpusel: ReadWrite<u32, CpuClockSelect::Register>),
26 (0x008 => _reserved1: u32),
27 (0x00C => pbasel: ReadWrite<u32, PeripheralBusXClockSelect::Register>),
28 (0x010 => pbbsel: ReadWrite<u32, PeripheralBusXClockSelect::Register>),
29 (0x014 => pbcsel: ReadWrite<u32, PeripheralBusXClockSelect::Register>),
30 (0x018 => pbdsel: ReadWrite<u32, PeripheralBusXClockSelect::Register>),
31 (0x01C => _reserved2: u32),
32 (0x020 => cpumask: ReadWrite<u32, ClockMaskCpu::Register>),
33 (0x024 => hsbmask: ReadWrite<u32, ClockMaskHsb::Register>),
34 (0x028 => pbamask: ReadWrite<u32, ClockMaskPba::Register>),
35 (0x02C => pbbmask: ReadWrite<u32, ClockMaskPbb::Register>),
36 (0x030 => pbcmask: ReadWrite<u32, ClockMaskPbc::Register>),
37 (0x034 => pbdmask: ReadWrite<u32, ClockMaskPbd::Register>),
38 (0x038 => _reserved3: [u32; 2]),
39 (0x040 => pbadivmask: ReadWrite<u32, DividedClockMask::Register>),
40 (0x044 => _reserved4: [u32; 4]),
41 (0x054 => cfdctrl: ReadWrite<u32, ClockFailureDetectorControl::Register>),
42 (0x058 => unlock: WriteOnly<u32, PmUnlock::Register>),
43 (0x05C => _reserved5: [u32; 25]),
44 (0x0C0 => ier: WriteOnly<u32, InterruptOrStatus::Register>),
45 (0x0C4 => idr: WriteOnly<u32, InterruptOrStatus::Register>),
46 (0x0C8 => imr: ReadOnly<u32, InterruptOrStatus::Register>),
47 (0x0CC => isr: ReadOnly<u32, InterruptOrStatus::Register>),
48 (0x0D0 => icr: WriteOnly<u32, InterruptOrStatus::Register>),
49 (0x0D4 => sr: ReadOnly<u32, InterruptOrStatus::Register>),
50 (0x0D8 => _reserved6),
51 (0x160 => ppcr: ReadWrite<u32, PeripheralPowerControl::Register>),
52 (0x164 => _reserved7),
53 (0x180 => rcause: ReadOnly<u32, ResetCause::Register>),
54 (0x184 => wcause: ReadOnly<u32, WakeCause::Register>),
55 (0x188 => awen: ReadWrite<u32, AsynchronousWakeUpEnable::Register>),
56 (0x18C => _protctrl: u32),
57 (0x190 => _reserved8),
58 (0x194 => fastsleep: ReadWrite<u32, FastSleep::Register>),
59 (0x198 => _reserved9),
60 (0x3F8 => config: ReadOnly<u32, Configuration::Register>),
61 (0x3FC => version: ReadOnly<u32, Version::Register>),
62 (0x400 => @END),
63 }
64}
65
66register_bitfields![u32,
67 MainClockControl [
68 MCSEL OFFSET(0) NUMBITS(3) []
79 ],
80
81 CpuClockSelect [
83 CPUDIV OFFSET(7) NUMBITS(1) [],
85
86 CPUSEL OFFSET(0) NUMBITS(3) []
88 ],
89
90 PeripheralBusXClockSelect [
92 PBDIV OFFSET(7) NUMBITS(1) [],
94
95 PBSEL OFFSET(0) NUMBITS(3) []
97 ],
98
99 ClockMaskCpu [
104 OCD 0
105 ],
106
107 ClockMaskHsb [
112 PDCA 0,
113 FLASHCALW 1,
114 FLASHCALW_PICOCACHE 2,
115 USBC 3,
116 CRCCU 4,
117 APBA_BRIDGE 5,
118 APBB_BRIDGE 6,
119 APBC_BRIDGE 7,
120 APBD_BRIDGE 8,
121 AESA 9
122 ],
123
124 ClockMaskPba [
129 IISC 0,
130 SPI 1,
131 TC0 2,
132 TC1 3,
133 TWIM0 4,
134 TWIS0 5,
135 TWIM1 6,
136 TWIS1 7,
137 USART0 8,
138 USART1 9,
139 USART2 10,
140 USART3 11,
141 ADCIFE 12,
142 DACC 13,
143 ACIFC 14,
144 GLOC 15,
145 ABDACB 16,
146 TRNG 17,
147 PARC 18,
148 CATB 19,
149 TWIM2 21,
150 TWIM3 22,
151 LCDCA 23
152 ],
153
154 ClockMaskPbb [
159 FLASHCALW 0,
160 HRAMC1 1,
161 HMATRIX 2,
162 PDCA 3,
163 CRCCU 4,
164 USBC 5,
165 PEVC 6
166 ],
167
168 ClockMaskPbc [
173 PM 0,
174 CHIPID 1,
175 SCIF 2,
176 FREQM 3,
177 GPIO 4
178 ],
179
180 ClockMaskPbd [
185 BPM 0,
186 BSCIF 1,
187 AST 2,
188 WDT 3,
189 EIC 4,
190 PICOUART 5
191 ],
192
193 DividedClockMask [
199 MASK OFFSET(0) NUMBITS(7) [
200 TIMER_CLOCK2 = 1 << 0,
202
203 TIMER_CLOCK3 = 1 << 2,
205
206 TIMER_CLOCK4 = 1 << 4,
208
209 TIMER_CLOCK5 = 1 << 6
211 ]
212 ],
213
214 ClockFailureDetectorControl [
215 SFV 31,
217
218 CFDEN 0
220 ],
221
222 PmUnlock [
223 KEY OFFSET(24) NUMBITS(8) [],
225
226 ADDR OFFSET(0) NUMBITS(10) []
228 ],
229
230 InterruptOrStatus [
231 AE 31,
233
234 WAKE 8,
236
237 CKRDY 5,
239
240 CFD 0
242 ],
243
244 PeripheralPowerControl [
246 FWBOD18 10,
248
249 FWBGREF 9,
251
252 VREGRCMASK 8,
254
255 ADCIFERCMASK 7,
257
258 PEVCRCMASK 6,
260
261 TWIS1RCMASK 5,
263
264 TWIS0RCMASK 4,
266
267 ASTRCMASK 3,
269
270 ACIFCRCMASK 2,
272
273 CATBRCMASK 1,
275
276 RSTPUN 0
278 ],
279
280 ResetCause [
281 BOD33 13,
283
284 POR33 10,
286
287 OCDRST 8,
289
290 BKUP 6,
292
293 WDT 3,
295
296 EXT 2,
298
299 BOD 1,
301
302 POR 0
304 ],
305
306 WakeCause [
307 AST 17,
308 EIC 16,
309 LCDCA 7,
310 PICOUART 6,
311 BOD33_IRQ 5,
312 BOD18_IRQ 4,
313 PSOK 3,
314 USBC 2,
315 TWIS1 1,
316 TWIS0 0
317 ],
318
319 AsynchronousWakeUpEnable [
321 LCDCA 7,
322 PICOUART 6,
323 BOD33_IRQ 5,
324 BOD18_IRQ 4,
325 PSOK 3,
326 USBC 2,
327 TWIS1 1,
328 TWIS0 0
329 ],
330
331 FastSleep [
338 DFLL 24,
339 RC1M 18,
340 RCFAST 17,
341 RC80 16,
342 PLL 8,
343 OSC 0
344 ],
345
346 Configuration [
347 HSBPEVC 7,
349
350 PBD 3,
352
353 PBC 2,
355
356 PBB 1,
358
359 PBA 0
361 ],
362
363 Version [
364 VARIANT OFFSET(16) NUMBITS(4) [],
366
367 VERSION OFFSET(0) NUMBITS(12) []
368 ]
369];
370
371pub enum MainClock {
372 RCSYS,
373 OSC0,
374 PLL,
375 DFLL,
376 RC80M,
377 RCFAST,
378 RC1M,
379}
380
381#[derive(Copy, Clone, Debug)]
382pub enum Clock {
383 HSB(HSBClock),
384 PBA(PBAClock),
385 PBB(PBBClock),
386 PBC(PBCClock),
387 PBD(PBDClock),
388}
389
390#[derive(Copy, Clone, Debug)]
391pub enum HSBClock {
392 PDCA,
393 FLASHCALW,
394 FLASHCALWP,
395 USBC,
396 CRCCU,
397 APBA,
398 APBB,
399 APBC,
400 APBD,
401 AESA,
402}
403
404#[derive(Copy, Clone, Debug)]
405pub enum PBAClock {
406 IISC,
407 SPI,
408 TC0,
409 TC1,
410 TWIM0,
411 TWIS0,
412 TWIM1,
413 TWIS1,
414 USART0,
415 USART1,
416 USART2,
417 USART3,
418 ADCIFE,
419 DACC,
420 ACIFC,
421 GLOC,
422 ABSACB,
423 TRNG,
424 PARC,
425 CATB,
426 NULL,
427 TWIM2,
428 TWIM3,
429 LCDCA,
430}
431
432#[derive(Copy, Clone, Debug)]
433pub enum PBBClock {
434 FLASHCALW,
435 HRAMC1,
436 HMATRIX,
437 PDCA,
438 CRCCU,
439 USBC,
440 PEVC,
441}
442
443#[derive(Copy, Clone, Debug)]
444pub enum PBCClock {
445 PM,
446 CHIPID,
447 SCIF,
448 FREQM,
449 GPIO,
450}
451
452#[derive(Copy, Clone, Debug)]
453pub enum PBDClock {
454 BPM,
455 BSCIF,
456 AST,
457 WDT,
458 EIC,
459 PICOUART,
460}
461
462#[derive(Copy, Clone, Debug, PartialEq)]
471pub enum OscillatorFrequency {
472 Frequency16MHz,
474}
475
476#[derive(Copy, Clone, Debug, PartialEq)]
477pub enum RcfastFrequency {
478 Frequency4MHz,
479 Frequency8MHz,
480 Frequency12MHz,
481}
482
483#[derive(Copy, Clone, Debug, PartialEq)]
491pub enum OscillatorStartup {
492 FastStart,
494
495 SlowStart,
497}
498
499#[derive(Copy, Clone, Debug, PartialEq)]
515pub enum SystemClockSource {
516 RcsysAt115kHz,
520
521 RC1M,
522
523 RCFAST {
524 frequency: RcfastFrequency,
525 },
526
527 ExternalOscillator {
531 frequency: OscillatorFrequency,
532 startup_mode: OscillatorStartup,
533 },
534
535 PllExternalOscillatorAt48MHz {
539 frequency: OscillatorFrequency,
540 startup_mode: OscillatorStartup,
541 },
542
543 DfllRc32kAt48MHz,
547
548 RC80M,
549}
550
551pub enum ClockMask {
552 RCSYS = 0x01,
553 RC1M = 0x02,
554 RCFAST = 0x04,
555 OSC0 = 0x08,
556 DFLL = 0x10,
557 PLL = 0x20,
558 RC80M = 0x40,
559}
560
561const HSB_MASK_OFFSET: u32 = 0x24;
562const PBA_MASK_OFFSET: u32 = 0x28;
563const PBB_MASK_OFFSET: u32 = 0x2C;
564const PBC_MASK_OFFSET: u32 = 0x30;
565const PBD_MASK_OFFSET: u32 = 0x34;
566
567const PM_BASE: usize = 0x400E0000;
568const PM_REGS: StaticRef<PmRegisters> = unsafe { StaticRef::new(PM_BASE as *const PmRegisters) };
569
570pub struct PowerManager {
574 system_clock_source: Cell<SystemClockSource>,
576
577 system_on_clocks: Cell<u32>,
579
580 system_initial_configs: Cell<bool>,
582}
583
584impl PowerManager {
585 pub const fn new() -> Self {
586 Self {
587 system_clock_source: Cell::new(SystemClockSource::RcsysAt115kHz),
589
590 system_on_clocks: Cell::new(ClockMask::RCSYS as u32),
591
592 system_initial_configs: Cell::new(false),
593 }
594 }
595}
596
597impl PowerManager {
598 pub unsafe fn setup_system_clock(
601 &self,
602 clock_source: SystemClockSource,
603 flash_controller: &flashcalw::FLASHCALW,
604 ) {
605 if !self.system_initial_configs.get() {
606 bpm::set_power_scaling(bpm::PowerScaling::PS2);
609
610 bscif::enable_rc32k();
612
613 flash_controller.enable_cache();
615
616 flash_controller.enable_high_speed_flash();
618
619 self.system_initial_configs.set(true);
620 }
621
622 match clock_source {
623 SystemClockSource::RcsysAt115kHz => {
624 flash_controller.set_wait_state(0);
627 select_main_clock(MainClock::RCSYS);
629 }
630
631 SystemClockSource::DfllRc32kAt48MHz => {
632 self.configure_48mhz_dfll();
634 flash_controller.set_wait_state(1);
636 select_main_clock(MainClock::DFLL);
638 }
639
640 SystemClockSource::ExternalOscillator {
641 frequency,
642 startup_mode,
643 } => {
644 self.configure_external_oscillator(frequency, startup_mode);
646 flash_controller.set_wait_state(0);
648 select_main_clock(MainClock::OSC0);
650 }
651
652 SystemClockSource::PllExternalOscillatorAt48MHz {
653 frequency,
654 startup_mode,
655 } => {
656 self.configure_external_oscillator_pll(frequency, startup_mode);
658 flash_controller.set_wait_state(1);
660 select_main_clock(MainClock::PLL);
662 }
663
664 SystemClockSource::RC80M => {
665 self.configure_80mhz_rc();
667
668 let cpusel = PM_REGS.cpusel.extract();
671 unlock(0x00000004);
672 PM_REGS.cpusel.modify_no_read(
673 cpusel,
674 CpuClockSelect::CPUDIV::SET + CpuClockSelect::CPUSEL::CLEAR,
675 );
676 while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
677
678 flash_controller.set_wait_state(1);
680 select_main_clock(MainClock::RC80M);
682 }
683
684 SystemClockSource::RCFAST { frequency } => {
685 if (self.system_on_clocks.get() & (ClockMask::RCFAST as u32)) != 0 {
688 select_main_clock(MainClock::RCSYS);
689 scif::disable_rcfast();
690 }
691
692 self.configure_rcfast(frequency);
694 flash_controller.set_wait_state(0);
696 select_main_clock(MainClock::RCFAST);
698 }
699
700 SystemClockSource::RC1M => {
701 self.configure_1mhz_rc();
703 flash_controller.set_wait_state(0);
705 select_main_clock(MainClock::RC1M);
707 }
708 }
709
710 self.system_clock_source.set(clock_source);
711 }
712
713 pub unsafe fn disable_system_clock(&self, clock_source: SystemClockSource) {
715 match clock_source {
718 SystemClockSource::RcsysAt115kHz => {
719 }
721
722 SystemClockSource::ExternalOscillator { .. } => {
723 if self.system_on_clocks.get() & (ClockMask::PLL as u32) == 0 {
725 scif::disable_osc_16mhz();
726 }
727 let clock_mask = self.system_on_clocks.get();
728 self.system_on_clocks
729 .set(clock_mask & !(ClockMask::OSC0 as u32));
730 }
731
732 SystemClockSource::PllExternalOscillatorAt48MHz { .. } => {
733 scif::disable_pll();
735 if self.system_on_clocks.get() & (ClockMask::OSC0 as u32) == 0 {
737 scif::disable_osc_16mhz();
738 }
739 let clock_mask = self.system_on_clocks.get();
740 self.system_on_clocks
741 .set(clock_mask & !(ClockMask::PLL as u32));
742 }
743
744 SystemClockSource::DfllRc32kAt48MHz => {
745 scif::disable_dfll_rc32k();
747 let clock_mask = self.system_on_clocks.get();
748 self.system_on_clocks
749 .set(clock_mask & !(ClockMask::DFLL as u32));
750 }
751
752 SystemClockSource::RC80M => {
753 scif::disable_rc_80mhz();
755
756 let cpusel = PM_REGS.cpusel.extract();
758 unlock(0x00000004);
759 PM_REGS.cpusel.modify_no_read(
760 cpusel,
761 CpuClockSelect::CPUDIV::CLEAR + CpuClockSelect::CPUSEL::CLEAR,
762 );
763 while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
764
765 let pbasel = PM_REGS.pbasel.extract();
767 unlock(0x0000000C);
768 PM_REGS.pbasel.modify_no_read(
769 pbasel,
770 PeripheralBusXClockSelect::PBDIV::CLEAR
771 + PeripheralBusXClockSelect::PBSEL::CLEAR,
772 );
773 while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
774
775 let pbbsel = PM_REGS.pbbsel.extract();
776 unlock(0x00000010);
777 PM_REGS.pbbsel.modify_no_read(
778 pbbsel,
779 PeripheralBusXClockSelect::PBDIV::CLEAR
780 + PeripheralBusXClockSelect::PBSEL::CLEAR,
781 );
782 while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
783
784 let pbcsel = PM_REGS.pbcsel.extract();
785 unlock(0x00000014);
786 PM_REGS.pbcsel.modify_no_read(
787 pbcsel,
788 PeripheralBusXClockSelect::PBDIV::CLEAR
789 + PeripheralBusXClockSelect::PBSEL::CLEAR,
790 );
791 while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
792
793 let pbdsel = PM_REGS.pbdsel.extract();
794 unlock(0x00000018);
795 PM_REGS.pbdsel.modify_no_read(
796 pbdsel,
797 PeripheralBusXClockSelect::PBDIV::CLEAR
798 + PeripheralBusXClockSelect::PBSEL::CLEAR,
799 );
800 while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
801
802 let clock_mask = self.system_on_clocks.get();
803 self.system_on_clocks
804 .set(clock_mask & !(ClockMask::RC80M as u32));
805 }
806
807 SystemClockSource::RCFAST { .. } => {
808 scif::disable_rcfast();
810 let clock_mask = self.system_on_clocks.get();
811 self.system_on_clocks
812 .set(clock_mask & !(ClockMask::RCFAST as u32));
813 }
814
815 SystemClockSource::RC1M => {
816 bscif::disable_rc_1mhz();
818 let clock_mask = self.system_on_clocks.get();
819 self.system_on_clocks
820 .set(clock_mask & !(ClockMask::RC1M as u32));
821 }
822 }
823 }
824
825 pub unsafe fn change_system_clock(
828 &self,
829 clock_source: SystemClockSource,
830 flash_controller: &flashcalw::FLASHCALW,
831 ) {
832 let prev_clock_source = self.system_clock_source.get();
834 if prev_clock_source == clock_source {
835 return;
836 }
837
838 self.setup_system_clock(clock_source, flash_controller);
840
841 if let SystemClockSource::RCFAST { .. } = clock_source {
844 if let SystemClockSource::RCFAST { .. } = prev_clock_source {
845 return;
846 }
847 }
848 self.disable_system_clock(prev_clock_source);
850 }
851
852 unsafe fn configure_48mhz_dfll(&self) {
855 scif::setup_dfll_rc32k_48mhz();
857
858 let clock_mask = self.system_on_clocks.get();
859 self.system_on_clocks
860 .set(clock_mask | ClockMask::DFLL as u32);
861 }
862
863 unsafe fn configure_external_oscillator(
865 &self,
866 frequency: OscillatorFrequency,
867 startup_mode: OscillatorStartup,
868 ) {
869 if (self.system_on_clocks.get() & ClockMask::PLL as u32) == 0 {
871 match frequency {
872 OscillatorFrequency::Frequency16MHz => match startup_mode {
873 OscillatorStartup::FastStart => scif::setup_osc_16mhz_fast_startup(),
874 OscillatorStartup::SlowStart => scif::setup_osc_16mhz_slow_startup(),
875 },
876 }
877 }
878
879 let clock_mask = self.system_on_clocks.get();
880 self.system_on_clocks
881 .set(clock_mask | ClockMask::OSC0 as u32);
882 }
883
884 unsafe fn configure_external_oscillator_pll(
886 &self,
887 frequency: OscillatorFrequency,
888 startup_mode: OscillatorStartup,
889 ) {
890 if (self.system_on_clocks.get() & ClockMask::OSC0 as u32) == 0 {
892 match frequency {
893 OscillatorFrequency::Frequency16MHz => match startup_mode {
894 OscillatorStartup::FastStart => scif::setup_osc_16mhz_fast_startup(),
895 OscillatorStartup::SlowStart => scif::setup_osc_16mhz_slow_startup(),
896 },
897 }
898 }
899
900 scif::setup_pll_osc_48mhz();
902
903 let clock_mask = self.system_on_clocks.get();
904 self.system_on_clocks
905 .set(clock_mask | ClockMask::PLL as u32);
906 }
907
908 unsafe fn configure_80mhz_rc(&self) {
909 scif::setup_rc_80mhz();
911
912 let pbasel = PM_REGS.pbasel.extract();
914 unlock(0x0000000C);
915 PM_REGS.pbasel.modify_no_read(
916 pbasel,
917 PeripheralBusXClockSelect::PBDIV::SET + PeripheralBusXClockSelect::PBSEL::CLEAR,
918 );
919 while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
920
921 let pbbsel = PM_REGS.pbbsel.extract();
922 unlock(0x00000010);
923 PM_REGS.pbbsel.modify_no_read(
924 pbbsel,
925 PeripheralBusXClockSelect::PBDIV::SET + PeripheralBusXClockSelect::PBSEL::CLEAR,
926 );
927 while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
928
929 let pbcsel = PM_REGS.pbcsel.extract();
930 unlock(0x00000014);
931 PM_REGS.pbcsel.modify_no_read(
932 pbcsel,
933 PeripheralBusXClockSelect::PBDIV::SET + PeripheralBusXClockSelect::PBSEL::CLEAR,
934 );
935 while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
936
937 let pbdsel = PM_REGS.pbdsel.extract();
938 unlock(0x00000018);
939 PM_REGS.pbdsel.modify_no_read(
940 pbdsel,
941 PeripheralBusXClockSelect::PBDIV::SET + PeripheralBusXClockSelect::PBSEL::CLEAR,
942 );
943 while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
944
945 let clock_mask = self.system_on_clocks.get();
946 self.system_on_clocks
947 .set(clock_mask | ClockMask::RC80M as u32);
948 }
949
950 unsafe fn configure_rcfast(&self, frequency: RcfastFrequency) {
951 match frequency {
953 RcfastFrequency::Frequency4MHz => {
954 scif::setup_rcfast_4mhz();
955 }
956 RcfastFrequency::Frequency8MHz => {
957 scif::setup_rcfast_8mhz();
958 }
959 RcfastFrequency::Frequency12MHz => {
960 scif::setup_rcfast_12mhz();
961 }
962 }
963
964 let clock_mask = self.system_on_clocks.get();
965 self.system_on_clocks
966 .set(clock_mask | ClockMask::RCFAST as u32);
967 }
968
969 unsafe fn configure_1mhz_rc(&self) {
970 bscif::setup_rc_1mhz();
972 let clock_mask = self.system_on_clocks.get();
973 self.system_on_clocks
974 .set(clock_mask | ClockMask::RC1M as u32);
975 }
976
977 pub fn get_system_frequency(&self) -> u32 {
978 match self.system_clock_source.get() {
980 SystemClockSource::RcsysAt115kHz => 115200,
981 SystemClockSource::DfllRc32kAt48MHz => 48000000,
982 SystemClockSource::ExternalOscillator { .. } => 16000000,
983 SystemClockSource::PllExternalOscillatorAt48MHz { .. } => 48000000,
984 SystemClockSource::RC80M => 40000000,
985 SystemClockSource::RCFAST { frequency } => match frequency {
986 RcfastFrequency::Frequency4MHz => 4300000,
987 RcfastFrequency::Frequency8MHz => 8200000,
988 RcfastFrequency::Frequency12MHz => 12000000,
989 },
990 SystemClockSource::RC1M => 1000000,
991 }
992 }
993}
994
995fn unlock(register_offset: u32) {
996 PM_REGS.unlock.set(0xAA000000 | register_offset);
997}
998
999fn select_main_clock(clock: MainClock) {
1000 unlock(0);
1001 PM_REGS.mcctrl.set(clock as u32);
1002}
1003
1004macro_rules! mask_clock {
1025 ($mask_offset:ident : $field:ident | $mask:expr) => {{
1026 unlock($mask_offset);
1027 let val = PM_REGS.$field.get() | ($mask);
1028 PM_REGS.$field.set(val);
1029 }};
1030
1031 ($mask_offset:ident : $field:ident & $mask:expr) => {{
1032 unlock($mask_offset);
1033 let val = PM_REGS.$field.get() & ($mask);
1034 PM_REGS.$field.set(val);
1035 }};
1036}
1037
1038macro_rules! get_clock {
1041 ($mask_offset:ident : $field:ident & $mask:expr) => {{
1042 unlock($mask_offset);
1043 (PM_REGS.$field.get() & ($mask)) != 0
1044 }};
1045}
1046
1047pub fn deep_sleep_ready() -> bool {
1074 let deep_sleep_hsbmask: FieldValue<u32, ClockMaskHsb::Register> = ClockMaskHsb::PDCA::SET
1083 + ClockMaskHsb::FLASHCALW::SET
1084 + ClockMaskHsb::FLASHCALW_PICOCACHE::SET
1085 + ClockMaskHsb::APBA_BRIDGE::SET
1086 + ClockMaskHsb::APBB_BRIDGE::SET
1087 + ClockMaskHsb::APBC_BRIDGE::SET
1088 + ClockMaskHsb::APBD_BRIDGE::SET;
1089
1090 let deep_sleep_pbamask: FieldValue<u32, ClockMaskPba::Register> =
1094 ClockMaskPba::TWIS0::SET + ClockMaskPba::TWIS1::SET;
1095
1096 let deep_sleep_pbbmask: FieldValue<u32, ClockMaskPbb::Register> =
1101 ClockMaskPbb::FLASHCALW::SET + ClockMaskPbb::HRAMC1::SET + ClockMaskPbb::PDCA::SET;
1102
1103 let hsb = PM_REGS.hsbmask.get() & !deep_sleep_hsbmask.mask() == 0;
1104 let pba = PM_REGS.pbamask.get() & !deep_sleep_pbamask.mask() == 0;
1105 let pbb = PM_REGS.pbbmask.get() & !deep_sleep_pbbmask.mask() == 0;
1106 let gpio = gpio::INTERRUPT_COUNT.load(Ordering::Relaxed) == 0;
1107 hsb && pba && pbb && gpio
1108}
1109
1110impl ClockInterface for Clock {
1111 fn is_enabled(&self) -> bool {
1112 match *self {
1113 Clock::HSB(v) => get_clock!(HSB_MASK_OFFSET: hsbmask & (1 << (v as u32))),
1114 Clock::PBA(v) => get_clock!(PBA_MASK_OFFSET: pbamask & (1 << (v as u32))),
1115 Clock::PBB(v) => get_clock!(PBB_MASK_OFFSET: pbbmask & (1 << (v as u32))),
1116 Clock::PBC(v) => get_clock!(PBC_MASK_OFFSET: pbcmask & (1 << (v as u32))),
1117 Clock::PBD(v) => get_clock!(PBD_MASK_OFFSET: pbdmask & (1 << (v as u32))),
1118 }
1119 }
1120
1121 fn enable(&self) {
1122 match *self {
1123 Clock::HSB(v) => mask_clock!(HSB_MASK_OFFSET: hsbmask | 1 << (v as u32)),
1124 Clock::PBA(v) => mask_clock!(PBA_MASK_OFFSET: pbamask | 1 << (v as u32)),
1125 Clock::PBB(v) => mask_clock!(PBB_MASK_OFFSET: pbbmask | 1 << (v as u32)),
1126 Clock::PBC(v) => mask_clock!(PBC_MASK_OFFSET: pbcmask | 1 << (v as u32)),
1127 Clock::PBD(v) => mask_clock!(PBD_MASK_OFFSET: pbdmask | 1 << (v as u32)),
1128 }
1129 }
1130
1131 fn disable(&self) {
1132 match *self {
1133 Clock::HSB(v) => mask_clock!(HSB_MASK_OFFSET: hsbmask & !(1 << (v as u32))),
1134 Clock::PBA(v) => mask_clock!(PBA_MASK_OFFSET: pbamask & !(1 << (v as u32))),
1135 Clock::PBB(v) => mask_clock!(PBB_MASK_OFFSET: pbbmask & !(1 << (v as u32))),
1136 Clock::PBC(v) => mask_clock!(PBC_MASK_OFFSET: pbcmask & !(1 << (v as u32))),
1137 Clock::PBD(v) => mask_clock!(PBD_MASK_OFFSET: pbdmask & !(1 << (v as u32))),
1138 }
1139 }
1140}
1141
1142pub fn enable_clock(clock: Clock) {
1143 match clock {
1144 Clock::HSB(v) => mask_clock!(HSB_MASK_OFFSET: hsbmask | 1 << (v as u32)),
1145 Clock::PBA(v) => mask_clock!(PBA_MASK_OFFSET: pbamask | 1 << (v as u32)),
1146 Clock::PBB(v) => mask_clock!(PBB_MASK_OFFSET: pbbmask | 1 << (v as u32)),
1147 Clock::PBC(v) => mask_clock!(PBC_MASK_OFFSET: pbcmask | 1 << (v as u32)),
1148 Clock::PBD(v) => mask_clock!(PBD_MASK_OFFSET: pbdmask | 1 << (v as u32)),
1149 }
1150}
1151
1152pub fn disable_clock(clock: Clock) {
1153 match clock {
1154 Clock::HSB(v) => mask_clock!(HSB_MASK_OFFSET: hsbmask & !(1 << (v as u32))),
1155 Clock::PBA(v) => mask_clock!(PBA_MASK_OFFSET: pbamask & !(1 << (v as u32))),
1156 Clock::PBB(v) => mask_clock!(PBB_MASK_OFFSET: pbbmask & !(1 << (v as u32))),
1157 Clock::PBC(v) => mask_clock!(PBC_MASK_OFFSET: pbcmask & !(1 << (v as u32))),
1158 Clock::PBD(v) => mask_clock!(PBD_MASK_OFFSET: pbdmask & !(1 << (v as u32))),
1159 }
1160}
1161
1162pub fn is_clock_enabled(clock: Clock) -> bool {
1163 match clock {
1164 Clock::HSB(v) => get_clock!(HSB_MASK_OFFSET: hsbmask & (1 << (v as u32))),
1165 Clock::PBA(v) => get_clock!(PBA_MASK_OFFSET: pbamask & (1 << (v as u32))),
1166 Clock::PBB(v) => get_clock!(PBB_MASK_OFFSET: pbbmask & (1 << (v as u32))),
1167 Clock::PBC(v) => get_clock!(PBC_MASK_OFFSET: pbcmask & (1 << (v as u32))),
1168 Clock::PBD(v) => get_clock!(PBD_MASK_OFFSET: pbdmask & (1 << (v as u32))),
1169 }
1170}