msp432/pcm.rs
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 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.
//! Power Control Manager (PCM)
use kernel::utilities::registers::interfaces::{Readable, Writeable};
use kernel::utilities::registers::{
register_bitfields, register_structs, ReadOnly, ReadWrite, WriteOnly,
};
use kernel::utilities::StaticRef;
const PCM_BASE: StaticRef<PcmRegisters> =
unsafe { StaticRef::new(0x4001_0000 as *const PcmRegisters) };
const PCMKEY: u32 = 0x695A; // for unlocking PCMCTL0 and PCMCTL1
register_structs! {
/// PCM
PcmRegisters {
/// Control 0 Register
(0x000 => ctl0: ReadWrite<u32, PCMCTL0::Register>),
/// Control 1 Register
(0x004 => ctl1: ReadWrite<u32, PCMCTL1::Register>),
/// Interrupt Enable Register
(0x008 => ie: ReadWrite<u32, PCMIE::Register>),
/// Interrupt Flag Register
(0x00C => ifg: ReadOnly<u32, PCMIFG::Register>),
/// Clear Interrupt Flag Register
(0x010 => clrifg: WriteOnly<u32, PCMCLRIFG::Register>),
(0x014 => @END),
}
}
register_bitfields![u32,
PCMCTL0 [
/// Active Mode Request
AMR OFFSET(0) NUMBITS(4) [
/// LDO based Active Mode at Core voltage setting 0.
LDOBasedActiveModeAtCoreVoltageSetting0 = 0,
/// LDO based Active Mode at Core voltage setting 1.
LDOBasedActiveModeAtCoreVoltageSetting1 = 1,
/// DC-DC based Active Mode at Core voltage setting 0.
DCDCBasedActiveModeAtCoreVoltageSetting0 = 4,
/// DC-DC based Active Mode at Core voltage setting 1.
DCDCBasedActiveModeAtCoreVoltageSetting1 = 5,
/// Low-Frequency Active Mode at Core voltage setting 0.
LowFrequencyActiveModeAtCoreVoltageSetting0 = 8,
/// Low-Frequency Active Mode at Core voltage setting 1.
LowFrequencyActiveModeAtCoreVoltageSetting1 = 9
],
/// Low Power Mode Request
LPMR OFFSET(4) NUMBITS(4) [
/// LPM3. Core voltage setting is similar to the mode from which LPM3 is entered.
LPM3CoreVoltageSettingIsSimilarToTheModeFromWhichLPM3IsEntered = 0,
/// LPM3.5. Core voltage setting 0.
LPM35CoreVoltageSetting0 = 10,
/// LPM4.5
LPM45 = 12
],
/// Current Power Mode
CPM OFFSET(8) NUMBITS(6) [
/// LDO based Active Mode at Core voltage setting 0.
LDOBasedActiveModeAtCoreVoltageSetting0 = 0,
/// LDO based Active Mode at Core voltage setting 1.
LDOBasedActiveModeAtCoreVoltageSetting1 = 1,
/// DC-DC based Active Mode at Core voltage setting 0.
DCDCBasedActiveModeAtCoreVoltageSetting0 = 4,
/// DC-DC based Active Mode at Core voltage setting 1.
DCDCBasedActiveModeAtCoreVoltageSetting1 = 5,
/// Low-Frequency Active Mode at Core voltage setting 0.
LowFrequencyActiveModeAtCoreVoltageSetting0 = 8,
/// Low-Frequency Active Mode at Core voltage setting 1.
LowFrequencyActiveModeAtCoreVoltageSetting1 = 9,
/// LDO based LPM0 at Core voltage setting 0.
LDOBasedLPM0AtCoreVoltageSetting0 = 16,
/// LDO based LPM0 at Core voltage setting 1.
LDOBasedLPM0AtCoreVoltageSetting1 = 17,
/// DC-DC based LPM0 at Core voltage setting 0.
DCDCBasedLPM0AtCoreVoltageSetting0 = 20,
/// DC-DC based LPM0 at Core voltage setting 1.
DCDCBasedLPM0AtCoreVoltageSetting1 = 21,
/// Low-Frequency LPM0 at Core voltage setting 0.
LowFrequencyLPM0AtCoreVoltageSetting0 = 24,
/// Low-Frequency LPM0 at Core voltage setting 1.
LowFrequencyLPM0AtCoreVoltageSetting1 = 25,
/// LPM3
LPM3 = 32
],
/// PCM key
PCMKEY OFFSET(16) NUMBITS(16) []
],
PCMCTL1 [
/// Lock LPM5
LOCKLPM5 OFFSET(0) NUMBITS(1) [
/// LPMx.5 configuration defaults to reset condition
LPMx5ConfigurationDefaultsToResetCondition = 0,
/// LPMx.5 configuration remains locked during LPMx.5 entry and exit
LPMx5ConfigurationRemainsLockedDuringLPMx5EntryAndExit = 1
],
/// Lock Backup
LOCKBKUP OFFSET(1) NUMBITS(1) [
/// Backup domain configuration defaults to reset condition
BackupDomainConfigurationDefaultsToResetCondition = 0,
/// Backup domain configuration remains locked during LPM3.5 entry and exit
BackupDomainConfigurationRemainsLockedDuringLPM35EntryAndExit = 1
],
/// Force LPM entry
FORCE_LPM_ENTRY OFFSET(2) NUMBITS(1) [
/// PCM aborts LPM3/LPMx.5 transition if the active clock configuration does not mee
FORCE_LPM_ENTRY_0 = 0,
/// PCM enters LPM3/LPMx.5 after shuting off the clocks forcefully. Application need
FORCE_LPM_ENTRY_1 = 1
],
/// Power mode request busy flag
PMR_BUSY OFFSET(8) NUMBITS(1) [],
/// PCM key
PCMKEY OFFSET(16) NUMBITS(16) []
],
PCMIE [
/// LPM invalid transition interrupt enable
LPM_INVALID_TR_IE OFFSET(0) NUMBITS(1) [
/// Disabled
Disabled = 0,
/// Enabled
Enabled = 1
],
/// LPM invalid clock interrupt enable
LPM_INVALID_CLK_IE OFFSET(1) NUMBITS(1) [
/// Disabled
Disabled = 0,
/// Enabled
Enabled = 1
],
/// Active mode invalid transition interrupt enable
AM_INVALID_TR_IE OFFSET(2) NUMBITS(1) [
/// Disabled
Disabled = 0,
/// Enabled
Enabled = 1
],
/// DC-DC error interrupt enable
DCDC_ERROR_IE OFFSET(6) NUMBITS(1) [
/// Disabled
Disabled = 0,
/// Enabled
Enabled = 1
]
],
PCMIFG [
/// LPM invalid transition flag
LPM_INVALID_TR_IFG OFFSET(0) NUMBITS(1) [],
/// LPM invalid clock flag
LPM_INVALID_CLK_IFG OFFSET(1) NUMBITS(1) [],
/// Active mode invalid transition flag
AM_INVALID_TR_IFG OFFSET(2) NUMBITS(1) [],
/// DC-DC error flag
DCDC_ERROR_IFG OFFSET(6) NUMBITS(1) []
],
PCMCLRIFG [
/// Clear LPM invalid transition flag
CLR_LPM_INVALID_TR_IFG OFFSET(0) NUMBITS(1) [],
/// Clear LPM invalid clock flag
CLR_LPM_INVALID_CLK_IFG OFFSET(1) NUMBITS(1) [],
/// Clear active mode invalid transition flag
CLR_AM_INVALID_TR_IFG OFFSET(2) NUMBITS(1) [],
/// Clear DC-DC error flag
CLR_DCDC_ERROR_IFG OFFSET(6) NUMBITS(1) []
]
];
pub struct Pcm {
registers: StaticRef<PcmRegisters>,
}
impl Pcm {
pub const fn new() -> Pcm {
Pcm {
registers: PCM_BASE,
}
}
// currently not sure about the interface, so just implement a simple
// method for activating AM_LDO_VCORE1 to provide enough power for 48MHz
pub fn set_high_power(&self) {
while self.registers.ctl1.is_set(PCMCTL1::PMR_BUSY) {}
self.registers.ctl0.write(
PCMCTL0::PCMKEY.val(PCMKEY) + PCMCTL0::AMR::DCDCBasedActiveModeAtCoreVoltageSetting1,
);
while self.registers.ctl1.is_set(PCMCTL1::PMR_BUSY) {}
}
}