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::registers::interfaces::{Readable, Writeable};
16use kernel::utilities::registers::{
17    register_bitfields, FieldValue, ReadOnly, ReadWrite, WriteOnly,
18};
19use kernel::utilities::StaticRef;
20
21#[repr(C)]
23struct PmRegisters {
24    mcctrl: ReadWrite<u32, MainClockControl::Register>,
25    cpusel: ReadWrite<u32, CpuClockSelect::Register>,
26    _reserved1: u32,
27    pbasel: ReadWrite<u32, PeripheralBusXClockSelect::Register>,
28    pbbsel: ReadWrite<u32, PeripheralBusXClockSelect::Register>,
29    pbcsel: ReadWrite<u32, PeripheralBusXClockSelect::Register>,
30    pbdsel: ReadWrite<u32, PeripheralBusXClockSelect::Register>,
31    _reserved2: u32,
32    cpumask: ReadWrite<u32, ClockMaskCpu::Register>, hsbmask: ReadWrite<u32, ClockMaskHsb::Register>,
34    pbamask: ReadWrite<u32, ClockMaskPba::Register>,
35    pbbmask: ReadWrite<u32, ClockMaskPbb::Register>,
36    pbcmask: ReadWrite<u32, ClockMaskPbc::Register>,
37    pbdmask: ReadWrite<u32, ClockMaskPbd::Register>,
38    _reserved3: [u32; 2],
39    pbadivmask: ReadWrite<u32, DividedClockMask::Register>, _reserved4: [u32; 4],
41    cfdctrl: ReadWrite<u32, ClockFailureDetectorControl::Register>,
42    unlock: WriteOnly<u32, PmUnlock::Register>,
43    _reserved5: [u32; 25],                            ier: WriteOnly<u32, InterruptOrStatus::Register>, idr: WriteOnly<u32, InterruptOrStatus::Register>,
46    imr: ReadOnly<u32, InterruptOrStatus::Register>,
47    isr: ReadOnly<u32, InterruptOrStatus::Register>,
48    icr: WriteOnly<u32, InterruptOrStatus::Register>,
49    sr: ReadOnly<u32, InterruptOrStatus::Register>,
50    _reserved6: [u32; 34],                                  ppcr: ReadWrite<u32, PeripheralPowerControl::Register>, _reserved7: [u32; 7],
53    rcause: ReadOnly<u32, ResetCause::Register>, wcause: ReadOnly<u32, WakeCause::Register>,
55    awen: ReadWrite<u32, AsynchronousWakeUpEnable::Register>,
56    _protctrl: u32, _reserved8: u32,
58    fastsleep: ReadWrite<u32, FastSleep::Register>,
59    _reserved9: [u32; 152],
60    config: ReadOnly<u32, Configuration::Register>, version: ReadOnly<u32, Version::Register>,
62}
63
64register_bitfields![u32,
65    MainClockControl [
66        MCSEL OFFSET(0) NUMBITS(3) []
77    ],
78
79    CpuClockSelect [
81        CPUDIV OFFSET(7) NUMBITS(1) [],
83
84        CPUSEL OFFSET(0) NUMBITS(3) []
86    ],
87
88    PeripheralBusXClockSelect [
90        PBDIV OFFSET(7) NUMBITS(1) [],
92
93        PBSEL OFFSET(0) NUMBITS(3) []
95    ],
96
97    ClockMaskCpu [
102        OCD 0
103    ],
104
105    ClockMaskHsb [
110        PDCA 0,
111        FLASHCALW 1,
112        FLASHCALW_PICOCACHE 2,
113        USBC 3,
114        CRCCU 4,
115        APBA_BRIDGE 5,
116        APBB_BRIDGE 6,
117        APBC_BRIDGE 7,
118        APBD_BRIDGE 8,
119        AESA 9
120    ],
121
122    ClockMaskPba [
127        IISC 0,
128        SPI 1,
129        TC0 2,
130        TC1 3,
131        TWIM0 4,
132        TWIS0 5,
133        TWIM1 6,
134        TWIS1 7,
135        USART0 8,
136        USART1 9,
137        USART2 10,
138        USART3 11,
139        ADCIFE 12,
140        DACC 13,
141        ACIFC 14,
142        GLOC 15,
143        ABDACB 16,
144        TRNG 17,
145        PARC 18,
146        CATB 19,
147        TWIM2 21,
148        TWIM3 22,
149        LCDCA 23
150    ],
151
152    ClockMaskPbb [
157        FLASHCALW 0,
158        HRAMC1 1,
159        HMATRIX 2,
160        PDCA 3,
161        CRCCU 4,
162        USBC 5,
163        PEVC 6
164    ],
165
166    ClockMaskPbc [
171        PM 0,
172        CHIPID 1,
173        SCIF 2,
174        FREQM 3,
175        GPIO 4
176    ],
177
178    ClockMaskPbd [
183        BPM 0,
184        BSCIF 1,
185        AST 2,
186        WDT 3,
187        EIC 4,
188        PICOUART 5
189    ],
190
191    DividedClockMask [
197        MASK OFFSET(0) NUMBITS(7) [
198            TIMER_CLOCK2 = 1 << 0,
200
201            TIMER_CLOCK3 = 1 << 2,
203
204            TIMER_CLOCK4 = 1 << 4,
206
207            TIMER_CLOCK5 = 1 << 6
209        ]
210    ],
211
212    ClockFailureDetectorControl [
213        SFV 31,
215
216        CFDEN 0
218    ],
219
220    PmUnlock [
221        KEY OFFSET(24) NUMBITS(8) [],
223
224        ADDR OFFSET(0) NUMBITS(10) []
226    ],
227
228    InterruptOrStatus [
229        AE 31,
231
232        WAKE 8,
234
235        CKRDY 5,
237
238        CFD 0
240    ],
241
242    PeripheralPowerControl [
244        FWBOD18 10,
246
247        FWBGREF 9,
249
250        VREGRCMASK 8,
252
253        ADCIFERCMASK 7,
255
256        PEVCRCMASK 6,
258
259        TWIS1RCMASK 5,
261
262        TWIS0RCMASK 4,
264
265        ASTRCMASK 3,
267
268        ACIFCRCMASK 2,
270
271        CATBRCMASK 1,
273
274        RSTPUN 0
276    ],
277
278    ResetCause [
279        BOD33 13,
281
282        POR33 10,
284
285        OCDRST 8,
287
288        BKUP 6,
290
291        WDT 3,
293
294        EXT 2,
296
297        BOD 1,
299
300        POR 0
302    ],
303
304    WakeCause [
305        AST 17,
306        EIC 16,
307        LCDCA 7,
308        PICOUART 6,
309        BOD33_IRQ 5,
310        BOD18_IRQ 4,
311        PSOK 3,
312        USBC 2,
313        TWIS1 1,
314        TWIS0 0
315    ],
316
317    AsynchronousWakeUpEnable [
319        LCDCA 7,
320        PICOUART 6,
321        BOD33_IRQ 5,
322        BOD18_IRQ 4,
323        PSOK 3,
324        USBC 2,
325        TWIS1 1,
326        TWIS0 0
327    ],
328
329    FastSleep [
336        DFLL 24,
337        RC1M 18,
338        RCFAST 17,
339        RC80 16,
340        PLL 8,
341        OSC 0
342    ],
343
344    Configuration [
345        HSBPEVC 7,
347
348        PBD 3,
350
351        PBC 2,
353
354        PBB 1,
356
357        PBA 0
359    ],
360
361    Version [
362        VARIANT OFFSET(16) NUMBITS(4) [],
364
365        VERSION OFFSET(0) NUMBITS(12) []
366    ]
367];
368
369pub enum MainClock {
370    RCSYS,
371    OSC0,
372    PLL,
373    DFLL,
374    RC80M,
375    RCFAST,
376    RC1M,
377}
378
379#[derive(Copy, Clone, Debug)]
380pub enum Clock {
381    HSB(HSBClock),
382    PBA(PBAClock),
383    PBB(PBBClock),
384    PBC(PBCClock),
385    PBD(PBDClock),
386}
387
388#[derive(Copy, Clone, Debug)]
389pub enum HSBClock {
390    PDCA,
391    FLASHCALW,
392    FLASHCALWP,
393    USBC,
394    CRCCU,
395    APBA,
396    APBB,
397    APBC,
398    APBD,
399    AESA,
400}
401
402#[derive(Copy, Clone, Debug)]
403pub enum PBAClock {
404    IISC,
405    SPI,
406    TC0,
407    TC1,
408    TWIM0,
409    TWIS0,
410    TWIM1,
411    TWIS1,
412    USART0,
413    USART1,
414    USART2,
415    USART3,
416    ADCIFE,
417    DACC,
418    ACIFC,
419    GLOC,
420    ABSACB,
421    TRNG,
422    PARC,
423    CATB,
424    NULL,
425    TWIM2,
426    TWIM3,
427    LCDCA,
428}
429
430#[derive(Copy, Clone, Debug)]
431pub enum PBBClock {
432    FLASHCALW,
433    HRAMC1,
434    HMATRIX,
435    PDCA,
436    CRCCU,
437    USBC,
438    PEVC,
439}
440
441#[derive(Copy, Clone, Debug)]
442pub enum PBCClock {
443    PM,
444    CHIPID,
445    SCIF,
446    FREQM,
447    GPIO,
448}
449
450#[derive(Copy, Clone, Debug)]
451pub enum PBDClock {
452    BPM,
453    BSCIF,
454    AST,
455    WDT,
456    EIC,
457    PICOUART,
458}
459
460#[derive(Copy, Clone, Debug, PartialEq)]
469pub enum OscillatorFrequency {
470    Frequency16MHz,
472}
473
474#[derive(Copy, Clone, Debug, PartialEq)]
475pub enum RcfastFrequency {
476    Frequency4MHz,
477    Frequency8MHz,
478    Frequency12MHz,
479}
480
481#[derive(Copy, Clone, Debug, PartialEq)]
489pub enum OscillatorStartup {
490    FastStart,
492
493    SlowStart,
495}
496
497#[derive(Copy, Clone, Debug, PartialEq)]
513pub enum SystemClockSource {
514    RcsysAt115kHz,
518
519    RC1M,
520
521    RCFAST {
522        frequency: RcfastFrequency,
523    },
524
525    ExternalOscillator {
529        frequency: OscillatorFrequency,
530        startup_mode: OscillatorStartup,
531    },
532
533    PllExternalOscillatorAt48MHz {
537        frequency: OscillatorFrequency,
538        startup_mode: OscillatorStartup,
539    },
540
541    DfllRc32kAt48MHz,
545
546    RC80M,
547}
548
549pub enum ClockMask {
550    RCSYS = 0x01,
551    RC1M = 0x02,
552    RCFAST = 0x04,
553    OSC0 = 0x08,
554    DFLL = 0x10,
555    PLL = 0x20,
556    RC80M = 0x40,
557}
558
559const HSB_MASK_OFFSET: u32 = 0x24;
560const PBA_MASK_OFFSET: u32 = 0x28;
561const PBB_MASK_OFFSET: u32 = 0x2C;
562const PBC_MASK_OFFSET: u32 = 0x30;
563const PBD_MASK_OFFSET: u32 = 0x34;
564
565const PM_BASE: usize = 0x400E0000;
566const PM_REGS: StaticRef<PmRegisters> = unsafe { StaticRef::new(PM_BASE as *const PmRegisters) };
567
568pub struct PowerManager {
572    system_clock_source: Cell<SystemClockSource>,
574
575    system_on_clocks: Cell<u32>,
577
578    system_initial_configs: Cell<bool>,
580}
581
582impl PowerManager {
583    pub const fn new() -> Self {
584        Self {
585            system_clock_source: Cell::new(SystemClockSource::RcsysAt115kHz),
587
588            system_on_clocks: Cell::new(ClockMask::RCSYS as u32),
589
590            system_initial_configs: Cell::new(false),
591        }
592    }
593}
594
595impl PowerManager {
596    pub unsafe fn setup_system_clock(
599        &self,
600        clock_source: SystemClockSource,
601        flash_controller: &flashcalw::FLASHCALW,
602    ) {
603        if !self.system_initial_configs.get() {
604            bpm::set_power_scaling(bpm::PowerScaling::PS2);
607
608            bscif::enable_rc32k();
610
611            flash_controller.enable_cache();
613
614            flash_controller.enable_high_speed_flash();
616
617            self.system_initial_configs.set(true);
618        }
619
620        match clock_source {
621            SystemClockSource::RcsysAt115kHz => {
622                flash_controller.set_wait_state(0);
625                select_main_clock(MainClock::RCSYS);
627            }
628
629            SystemClockSource::DfllRc32kAt48MHz => {
630                self.configure_48mhz_dfll();
632                flash_controller.set_wait_state(1);
634                select_main_clock(MainClock::DFLL);
636            }
637
638            SystemClockSource::ExternalOscillator {
639                frequency,
640                startup_mode,
641            } => {
642                self.configure_external_oscillator(frequency, startup_mode);
644                flash_controller.set_wait_state(0);
646                select_main_clock(MainClock::OSC0);
648            }
649
650            SystemClockSource::PllExternalOscillatorAt48MHz {
651                frequency,
652                startup_mode,
653            } => {
654                self.configure_external_oscillator_pll(frequency, startup_mode);
656                flash_controller.set_wait_state(1);
658                select_main_clock(MainClock::PLL);
660            }
661
662            SystemClockSource::RC80M => {
663                self.configure_80mhz_rc();
665
666                let cpusel = PM_REGS.cpusel.extract();
669                unlock(0x00000004);
670                PM_REGS.cpusel.modify_no_read(
671                    cpusel,
672                    CpuClockSelect::CPUDIV::SET + CpuClockSelect::CPUSEL::CLEAR,
673                );
674                while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
675
676                flash_controller.set_wait_state(1);
678                select_main_clock(MainClock::RC80M);
680            }
681
682            SystemClockSource::RCFAST { frequency } => {
683                if (self.system_on_clocks.get() & (ClockMask::RCFAST as u32)) != 0 {
686                    select_main_clock(MainClock::RCSYS);
687                    scif::disable_rcfast();
688                }
689
690                self.configure_rcfast(frequency);
692                flash_controller.set_wait_state(0);
694                select_main_clock(MainClock::RCFAST);
696            }
697
698            SystemClockSource::RC1M => {
699                self.configure_1mhz_rc();
701                flash_controller.set_wait_state(0);
703                select_main_clock(MainClock::RC1M);
705            }
706        }
707
708        self.system_clock_source.set(clock_source);
709    }
710
711    pub unsafe fn disable_system_clock(&self, clock_source: SystemClockSource) {
713        match clock_source {
716            SystemClockSource::RcsysAt115kHz => {
717                }
719
720            SystemClockSource::ExternalOscillator { .. } => {
721                if self.system_on_clocks.get() & (ClockMask::PLL as u32) == 0 {
723                    scif::disable_osc_16mhz();
724                }
725                let clock_mask = self.system_on_clocks.get();
726                self.system_on_clocks
727                    .set(clock_mask & !(ClockMask::OSC0 as u32));
728            }
729
730            SystemClockSource::PllExternalOscillatorAt48MHz { .. } => {
731                scif::disable_pll();
733                if self.system_on_clocks.get() & (ClockMask::OSC0 as u32) == 0 {
735                    scif::disable_osc_16mhz();
736                }
737                let clock_mask = self.system_on_clocks.get();
738                self.system_on_clocks
739                    .set(clock_mask & !(ClockMask::PLL as u32));
740            }
741
742            SystemClockSource::DfllRc32kAt48MHz => {
743                scif::disable_dfll_rc32k();
745                let clock_mask = self.system_on_clocks.get();
746                self.system_on_clocks
747                    .set(clock_mask & !(ClockMask::DFLL as u32));
748            }
749
750            SystemClockSource::RC80M => {
751                scif::disable_rc_80mhz();
753
754                let cpusel = PM_REGS.cpusel.extract();
756                unlock(0x00000004);
757                PM_REGS.cpusel.modify_no_read(
758                    cpusel,
759                    CpuClockSelect::CPUDIV::CLEAR + CpuClockSelect::CPUSEL::CLEAR,
760                );
761                while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
762
763                let pbasel = PM_REGS.pbasel.extract();
765                unlock(0x0000000C);
766                PM_REGS.pbasel.modify_no_read(
767                    pbasel,
768                    PeripheralBusXClockSelect::PBDIV::CLEAR
769                        + PeripheralBusXClockSelect::PBSEL::CLEAR,
770                );
771                while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
772
773                let pbbsel = PM_REGS.pbbsel.extract();
774                unlock(0x00000010);
775                PM_REGS.pbbsel.modify_no_read(
776                    pbbsel,
777                    PeripheralBusXClockSelect::PBDIV::CLEAR
778                        + PeripheralBusXClockSelect::PBSEL::CLEAR,
779                );
780                while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
781
782                let pbcsel = PM_REGS.pbcsel.extract();
783                unlock(0x00000014);
784                PM_REGS.pbcsel.modify_no_read(
785                    pbcsel,
786                    PeripheralBusXClockSelect::PBDIV::CLEAR
787                        + PeripheralBusXClockSelect::PBSEL::CLEAR,
788                );
789                while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
790
791                let pbdsel = PM_REGS.pbdsel.extract();
792                unlock(0x00000018);
793                PM_REGS.pbdsel.modify_no_read(
794                    pbdsel,
795                    PeripheralBusXClockSelect::PBDIV::CLEAR
796                        + PeripheralBusXClockSelect::PBSEL::CLEAR,
797                );
798                while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
799
800                let clock_mask = self.system_on_clocks.get();
801                self.system_on_clocks
802                    .set(clock_mask & !(ClockMask::RC80M as u32));
803            }
804
805            SystemClockSource::RCFAST { .. } => {
806                scif::disable_rcfast();
808                let clock_mask = self.system_on_clocks.get();
809                self.system_on_clocks
810                    .set(clock_mask & !(ClockMask::RCFAST as u32));
811            }
812
813            SystemClockSource::RC1M => {
814                bscif::disable_rc_1mhz();
816                let clock_mask = self.system_on_clocks.get();
817                self.system_on_clocks
818                    .set(clock_mask & !(ClockMask::RC1M as u32));
819            }
820        }
821    }
822
823    pub unsafe fn change_system_clock(
826        &self,
827        clock_source: SystemClockSource,
828        flash_controller: &flashcalw::FLASHCALW,
829    ) {
830        let prev_clock_source = self.system_clock_source.get();
832        if prev_clock_source == clock_source {
833            return;
834        }
835
836        self.setup_system_clock(clock_source, flash_controller);
838
839        if let SystemClockSource::RCFAST { .. } = clock_source {
842            if let SystemClockSource::RCFAST { .. } = prev_clock_source {
843                return;
844            }
845        }
846        self.disable_system_clock(prev_clock_source);
848    }
849
850    unsafe fn configure_48mhz_dfll(&self) {
853        scif::setup_dfll_rc32k_48mhz();
855
856        let clock_mask = self.system_on_clocks.get();
857        self.system_on_clocks
858            .set(clock_mask | ClockMask::DFLL as u32);
859    }
860
861    unsafe fn configure_external_oscillator(
863        &self,
864        frequency: OscillatorFrequency,
865        startup_mode: OscillatorStartup,
866    ) {
867        if (self.system_on_clocks.get() & ClockMask::PLL as u32) == 0 {
869            match frequency {
870                OscillatorFrequency::Frequency16MHz => match startup_mode {
871                    OscillatorStartup::FastStart => scif::setup_osc_16mhz_fast_startup(),
872                    OscillatorStartup::SlowStart => scif::setup_osc_16mhz_slow_startup(),
873                },
874            }
875        }
876
877        let clock_mask = self.system_on_clocks.get();
878        self.system_on_clocks
879            .set(clock_mask | ClockMask::OSC0 as u32);
880    }
881
882    unsafe fn configure_external_oscillator_pll(
884        &self,
885        frequency: OscillatorFrequency,
886        startup_mode: OscillatorStartup,
887    ) {
888        if (self.system_on_clocks.get() & ClockMask::OSC0 as u32) == 0 {
890            match frequency {
891                OscillatorFrequency::Frequency16MHz => match startup_mode {
892                    OscillatorStartup::FastStart => scif::setup_osc_16mhz_fast_startup(),
893                    OscillatorStartup::SlowStart => scif::setup_osc_16mhz_slow_startup(),
894                },
895            }
896        }
897
898        scif::setup_pll_osc_48mhz();
900
901        let clock_mask = self.system_on_clocks.get();
902        self.system_on_clocks
903            .set(clock_mask | ClockMask::PLL as u32);
904    }
905
906    unsafe fn configure_80mhz_rc(&self) {
907        scif::setup_rc_80mhz();
909
910        let pbasel = PM_REGS.pbasel.extract();
912        unlock(0x0000000C);
913        PM_REGS.pbasel.modify_no_read(
914            pbasel,
915            PeripheralBusXClockSelect::PBDIV::SET + PeripheralBusXClockSelect::PBSEL::CLEAR,
916        );
917        while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
918
919        let pbbsel = PM_REGS.pbbsel.extract();
920        unlock(0x00000010);
921        PM_REGS.pbbsel.modify_no_read(
922            pbbsel,
923            PeripheralBusXClockSelect::PBDIV::SET + PeripheralBusXClockSelect::PBSEL::CLEAR,
924        );
925        while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
926
927        let pbcsel = PM_REGS.pbcsel.extract();
928        unlock(0x00000014);
929        PM_REGS.pbcsel.modify_no_read(
930            pbcsel,
931            PeripheralBusXClockSelect::PBDIV::SET + PeripheralBusXClockSelect::PBSEL::CLEAR,
932        );
933        while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
934
935        let pbdsel = PM_REGS.pbdsel.extract();
936        unlock(0x00000018);
937        PM_REGS.pbdsel.modify_no_read(
938            pbdsel,
939            PeripheralBusXClockSelect::PBDIV::SET + PeripheralBusXClockSelect::PBSEL::CLEAR,
940        );
941        while PM_REGS.sr.matches_all(InterruptOrStatus::CKRDY::CLEAR) {}
942
943        let clock_mask = self.system_on_clocks.get();
944        self.system_on_clocks
945            .set(clock_mask | ClockMask::RC80M as u32);
946    }
947
948    unsafe fn configure_rcfast(&self, frequency: RcfastFrequency) {
949        match frequency {
951            RcfastFrequency::Frequency4MHz => {
952                scif::setup_rcfast_4mhz();
953            }
954            RcfastFrequency::Frequency8MHz => {
955                scif::setup_rcfast_8mhz();
956            }
957            RcfastFrequency::Frequency12MHz => {
958                scif::setup_rcfast_12mhz();
959            }
960        }
961
962        let clock_mask = self.system_on_clocks.get();
963        self.system_on_clocks
964            .set(clock_mask | ClockMask::RCFAST as u32);
965    }
966
967    unsafe fn configure_1mhz_rc(&self) {
968        bscif::setup_rc_1mhz();
970        let clock_mask = self.system_on_clocks.get();
971        self.system_on_clocks
972            .set(clock_mask | ClockMask::RC1M as u32);
973    }
974
975    pub fn get_system_frequency(&self) -> u32 {
976        match self.system_clock_source.get() {
978            SystemClockSource::RcsysAt115kHz => 115200,
979            SystemClockSource::DfllRc32kAt48MHz => 48000000,
980            SystemClockSource::ExternalOscillator { .. } => 16000000,
981            SystemClockSource::PllExternalOscillatorAt48MHz { .. } => 48000000,
982            SystemClockSource::RC80M => 40000000,
983            SystemClockSource::RCFAST { frequency } => match frequency {
984                RcfastFrequency::Frequency4MHz => 4300000,
985                RcfastFrequency::Frequency8MHz => 8200000,
986                RcfastFrequency::Frequency12MHz => 12000000,
987            },
988            SystemClockSource::RC1M => 1000000,
989        }
990    }
991}
992
993fn unlock(register_offset: u32) {
994    PM_REGS.unlock.set(0xAA000000 | register_offset);
995}
996
997fn select_main_clock(clock: MainClock) {
998    unlock(0);
999    PM_REGS.mcctrl.set(clock as u32);
1000}
1001
1002macro_rules! mask_clock {
1023    ($mask_offset:ident : $field:ident | $mask:expr) => {{
1024        unlock($mask_offset);
1025        let val = PM_REGS.$field.get() | ($mask);
1026        PM_REGS.$field.set(val);
1027    }};
1028
1029    ($mask_offset:ident : $field:ident & $mask:expr) => {{
1030        unlock($mask_offset);
1031        let val = PM_REGS.$field.get() & ($mask);
1032        PM_REGS.$field.set(val);
1033    }};
1034}
1035
1036macro_rules! get_clock {
1039    ($mask_offset:ident : $field:ident & $mask:expr) => {{
1040        unlock($mask_offset);
1041        (PM_REGS.$field.get() & ($mask)) != 0
1042    }};
1043}
1044
1045pub fn deep_sleep_ready() -> bool {
1072    let deep_sleep_hsbmask: FieldValue<u32, ClockMaskHsb::Register> = ClockMaskHsb::PDCA::SET
1081        + ClockMaskHsb::FLASHCALW::SET
1082        + ClockMaskHsb::FLASHCALW_PICOCACHE::SET
1083        + ClockMaskHsb::APBA_BRIDGE::SET
1084        + ClockMaskHsb::APBB_BRIDGE::SET
1085        + ClockMaskHsb::APBC_BRIDGE::SET
1086        + ClockMaskHsb::APBD_BRIDGE::SET;
1087
1088    let deep_sleep_pbamask: FieldValue<u32, ClockMaskPba::Register> =
1092        ClockMaskPba::TWIS0::SET + ClockMaskPba::TWIS1::SET;
1093
1094    let deep_sleep_pbbmask: FieldValue<u32, ClockMaskPbb::Register> =
1099        ClockMaskPbb::FLASHCALW::SET + ClockMaskPbb::HRAMC1::SET + ClockMaskPbb::PDCA::SET;
1100
1101    let hsb = PM_REGS.hsbmask.get() & !deep_sleep_hsbmask.mask() == 0;
1102    let pba = PM_REGS.pbamask.get() & !deep_sleep_pbamask.mask() == 0;
1103    let pbb = PM_REGS.pbbmask.get() & !deep_sleep_pbbmask.mask() == 0;
1104    let gpio = gpio::INTERRUPT_COUNT.load(Ordering::Relaxed) == 0;
1105    hsb && pba && pbb && gpio
1106}
1107
1108impl ClockInterface for Clock {
1109    fn is_enabled(&self) -> bool {
1110        match *self {
1111            Clock::HSB(v) => get_clock!(HSB_MASK_OFFSET: hsbmask & (1 << (v as u32))),
1112            Clock::PBA(v) => get_clock!(PBA_MASK_OFFSET: pbamask & (1 << (v as u32))),
1113            Clock::PBB(v) => get_clock!(PBB_MASK_OFFSET: pbbmask & (1 << (v as u32))),
1114            Clock::PBC(v) => get_clock!(PBC_MASK_OFFSET: pbcmask & (1 << (v as u32))),
1115            Clock::PBD(v) => get_clock!(PBD_MASK_OFFSET: pbdmask & (1 << (v as u32))),
1116        }
1117    }
1118
1119    fn enable(&self) {
1120        match *self {
1121            Clock::HSB(v) => mask_clock!(HSB_MASK_OFFSET: hsbmask | 1 << (v as u32)),
1122            Clock::PBA(v) => mask_clock!(PBA_MASK_OFFSET: pbamask | 1 << (v as u32)),
1123            Clock::PBB(v) => mask_clock!(PBB_MASK_OFFSET: pbbmask | 1 << (v as u32)),
1124            Clock::PBC(v) => mask_clock!(PBC_MASK_OFFSET: pbcmask | 1 << (v as u32)),
1125            Clock::PBD(v) => mask_clock!(PBD_MASK_OFFSET: pbdmask | 1 << (v as u32)),
1126        }
1127    }
1128
1129    fn disable(&self) {
1130        match *self {
1131            Clock::HSB(v) => mask_clock!(HSB_MASK_OFFSET: hsbmask & !(1 << (v as u32))),
1132            Clock::PBA(v) => mask_clock!(PBA_MASK_OFFSET: pbamask & !(1 << (v as u32))),
1133            Clock::PBB(v) => mask_clock!(PBB_MASK_OFFSET: pbbmask & !(1 << (v as u32))),
1134            Clock::PBC(v) => mask_clock!(PBC_MASK_OFFSET: pbcmask & !(1 << (v as u32))),
1135            Clock::PBD(v) => mask_clock!(PBD_MASK_OFFSET: pbdmask & !(1 << (v as u32))),
1136        }
1137    }
1138}
1139
1140pub fn enable_clock(clock: Clock) {
1141    match clock {
1142        Clock::HSB(v) => mask_clock!(HSB_MASK_OFFSET: hsbmask | 1 << (v as u32)),
1143        Clock::PBA(v) => mask_clock!(PBA_MASK_OFFSET: pbamask | 1 << (v as u32)),
1144        Clock::PBB(v) => mask_clock!(PBB_MASK_OFFSET: pbbmask | 1 << (v as u32)),
1145        Clock::PBC(v) => mask_clock!(PBC_MASK_OFFSET: pbcmask | 1 << (v as u32)),
1146        Clock::PBD(v) => mask_clock!(PBD_MASK_OFFSET: pbdmask | 1 << (v as u32)),
1147    }
1148}
1149
1150pub fn disable_clock(clock: Clock) {
1151    match clock {
1152        Clock::HSB(v) => mask_clock!(HSB_MASK_OFFSET: hsbmask & !(1 << (v as u32))),
1153        Clock::PBA(v) => mask_clock!(PBA_MASK_OFFSET: pbamask & !(1 << (v as u32))),
1154        Clock::PBB(v) => mask_clock!(PBB_MASK_OFFSET: pbbmask & !(1 << (v as u32))),
1155        Clock::PBC(v) => mask_clock!(PBC_MASK_OFFSET: pbcmask & !(1 << (v as u32))),
1156        Clock::PBD(v) => mask_clock!(PBD_MASK_OFFSET: pbdmask & !(1 << (v as u32))),
1157    }
1158}
1159
1160pub fn is_clock_enabled(clock: Clock) -> bool {
1161    match clock {
1162        Clock::HSB(v) => get_clock!(HSB_MASK_OFFSET: hsbmask & (1 << (v as u32))),
1163        Clock::PBA(v) => get_clock!(PBA_MASK_OFFSET: pbamask & (1 << (v as u32))),
1164        Clock::PBB(v) => get_clock!(PBB_MASK_OFFSET: pbbmask & (1 << (v as u32))),
1165        Clock::PBC(v) => get_clock!(PBC_MASK_OFFSET: pbcmask & (1 << (v as u32))),
1166        Clock::PBD(v) => get_clock!(PBD_MASK_OFFSET: pbdmask & (1 << (v as u32))),
1167    }
1168}