1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
//! API for power management (PMC) - always on //! //! The PMC peripheral is described in the user manual, chapter 13. //! //! We are mostly concerned with power to analog peripherals. //! crate::wrap_always_on_peripheral!(Pmc, PMC); // The UM does not list everything. // This is what `fsl_power.h` from the SDK reveals: // // kPDRUNCFG_PD_DCDC = (1UL << 0), // kPDRUNCFG_PD_BIAS = (1UL << 1), // kPDRUNCFG_PD_BODCORE = (1UL << 2), // kPDRUNCFG_PD_BODVBAT = (1UL << 3), // kPDRUNCFG_PD_FRO1M = (1UL << 4), // kPDRUNCFG_PD_FRO192M = (1UL << 5), // kPDRUNCFG_PD_FRO32K = (1UL << 6), // kPDRUNCFG_PD_XTAL32K = (1UL << 7), // kPDRUNCFG_PD_XTAL32M = (1UL << 8), // kPDRUNCFG_PD_PLL0 = (1UL << 9), // kPDRUNCFG_PD_PLL1 = (1UL << 10), // kPDRUNCFG_PD_USB0_PHY = (1UL << 11), // kPDRUNCFG_PD_USB1_PHY = (1UL << 12), // kPDRUNCFG_PD_COMP = (1UL << 13), // kPDRUNCFG_PD_TEMPSENS = (1UL << 14), // kPDRUNCFG_PD_GPADC = (1UL << 15), // kPDRUNCFG_PD_LDOMEM = (1UL << 16), // kPDRUNCFG_PD_LDODEEPSLEEP = (1UL << 17), // kPDRUNCFG_PD_LDOUSBHS = (1UL << 18), // kPDRUNCFG_PD_LDOGPADC = (1UL << 19), // kPDRUNCFG_PD_LDOXO32M = (1UL << 20), // kPDRUNCFG_PD_LDOFLASHNV = (1UL << 21), // kPDRUNCFG_PD_RNG = (1UL << 22), // kPDRUNCFG_PD_PLL0_SSCG = (1UL << 23), // kPDRUNCFG_PD_ROM = (1UL << 24), impl Pmc { /// Enables the power for a peripheral or other hardware component pub fn power_on<P: PowerControl>(&mut self, peripheral: &mut P) { peripheral.powered_on(self); } /// Disable the power pub fn power_off<P: PowerControl>(&mut self, peripheral: &mut P) { peripheral.powered_off(self); } /// Check if peripheral is powered pub fn is_powered<P: PowerControl>(&self, peripheral: &P) -> bool { peripheral.is_powered(&self) } } pub trait PowerControl { /// Internal method fn powered_on(&self, pmc: &mut Pmc); /// Internal method fn powered_off(&self, pmc: &mut Pmc); /// Internal method fn is_powered(&self, pmc: &Pmc) -> bool; } // impl ClockControl for raw::UTICK { // fn enable_clock<'h>(&self, h: &'h mut Handle) -> &'h mut Handle { // h.ahbclkctrl1.modify(|_, w| w.utick0().enable()); // h // } // fn disable_clock<'h>(&self, h: &'h mut Handle) -> &'h mut Handle { // h.ahbclkctrl1.modify(|_, w| w.utick0().disable()); // h // } // fn is_clock_enabled(&self, h: &Handle) -> bool { // h.ahbclkctrl1.read().utick0().is_enable() // } // } // impl PowerControl for raw::USB0 { // fn powered_on(&self, pmc: &mut Pmc) { // // Enable the power to the USB0 PHY by clearing the bit PDEN_USBFSPHY in the PDRUNCFG0 register // pmc.raw // .pdruncfg0 // .modify(|_, w| w.pden_usbfsphy().poweredon()); // } // /// Internal method // fn powered_off(&self, pmc: &mut Pmc) { // pmc.raw // .pdruncfg0 // .modify(|_, w| w.pden_usbfsphy().poweredoff()); // } // /// Internal method // fn is_powered(&self, pmc: &Pmc) -> bool { // pmc.raw.pdruncfg0.read().pden_usbfsphy().is_poweredon() // } // } // TODO: use the clr/set registers macro_rules! impl_power_control { ($power_control:ty, $register:ident) => { impl PowerControl for $power_control { fn powered_on(&self, pmc: &mut Pmc) { // pmc.raw.pdruncfg0clr.write(|w| w.bits(1u32 << <proper offset>)); pmc.raw.pdruncfg0.modify(|_, w| w.$register().poweredon()); } fn powered_off(&self, pmc: &mut Pmc) { pmc.raw.pdruncfg0.modify(|_, w| w.$register().poweredoff()); } fn is_powered(&self, pmc: &Pmc) -> bool { pmc.raw.pdruncfg0.read().$register().is_poweredon() } } }; ($power_control:ty, $register1:ident, $register2:ident) => { impl PowerControl for $power_control { fn powered_on(&self, pmc: &mut Pmc) { pmc.raw.pdruncfg0.modify(|_, w| w.$register1().poweredon()); pmc.raw.pdruncfg0.modify(|_, w| w.$register2().poweredon()); } fn powered_off(&self, pmc: &mut Pmc) { pmc.raw.pdruncfg0.modify(|_, w| w.$register1().poweredoff()); pmc.raw.pdruncfg0.modify(|_, w| w.$register2().poweredoff()); } fn is_powered(&self, pmc: &Pmc) -> bool { pmc.raw.pdruncfg0.read().$register1().is_poweredon() && pmc.raw.pdruncfg0.read().$register2().is_poweredon() } } }; } // well maybe there needs to be a USBFS peripheral with power control, // and on top of that USBFSD, USBFSHM, USBFSHS... to make this all logical. impl_power_control!(raw::USB0, pden_usbfsphy); impl_power_control!(raw::USBPHY, pden_usbhsphy, pden_ldousbhs); impl_power_control!(raw::ADC0, pden_auxbias); impl_power_control!(crate::typestates::ClocksSupport32KhzFroToken, pden_fro32k);