msp432/
pcm.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Power Control Manager (PCM)
6
7use kernel::utilities::registers::interfaces::{Readable, Writeable};
8use kernel::utilities::registers::{
9    register_bitfields, register_structs, ReadOnly, ReadWrite, WriteOnly,
10};
11use kernel::utilities::StaticRef;
12
13const PCM_BASE: StaticRef<PcmRegisters> =
14    unsafe { StaticRef::new(0x4001_0000 as *const PcmRegisters) };
15
16const PCMKEY: u32 = 0x695A; // for unlocking PCMCTL0 and PCMCTL1
17
18register_structs! {
19    /// PCM
20    PcmRegisters {
21        /// Control 0 Register
22        (0x000 => ctl0: ReadWrite<u32, PCMCTL0::Register>),
23        /// Control 1 Register
24        (0x004 => ctl1: ReadWrite<u32, PCMCTL1::Register>),
25        /// Interrupt Enable Register
26        (0x008 => ie: ReadWrite<u32, PCMIE::Register>),
27        /// Interrupt Flag Register
28        (0x00C => ifg: ReadOnly<u32, PCMIFG::Register>),
29        /// Clear Interrupt Flag Register
30        (0x010 => clrifg: WriteOnly<u32, PCMCLRIFG::Register>),
31        (0x014 => @END),
32    }
33}
34
35register_bitfields![u32,
36    PCMCTL0 [
37        /// Active Mode Request
38        AMR OFFSET(0) NUMBITS(4) [
39            /// LDO based Active Mode at Core voltage setting 0.
40            LDOBasedActiveModeAtCoreVoltageSetting0 = 0,
41            /// LDO based Active Mode at Core voltage setting 1.
42            LDOBasedActiveModeAtCoreVoltageSetting1 = 1,
43            /// DC-DC based Active Mode at Core voltage setting 0.
44            DCDCBasedActiveModeAtCoreVoltageSetting0 = 4,
45            /// DC-DC based Active Mode at Core voltage setting 1.
46            DCDCBasedActiveModeAtCoreVoltageSetting1 = 5,
47            /// Low-Frequency Active Mode at Core voltage setting 0.
48            LowFrequencyActiveModeAtCoreVoltageSetting0 = 8,
49            /// Low-Frequency Active Mode at Core voltage setting 1.
50            LowFrequencyActiveModeAtCoreVoltageSetting1 = 9
51        ],
52        /// Low Power Mode Request
53        LPMR OFFSET(4) NUMBITS(4) [
54            /// LPM3. Core voltage setting is similar to the mode from which LPM3 is entered.
55            LPM3CoreVoltageSettingIsSimilarToTheModeFromWhichLPM3IsEntered = 0,
56            /// LPM3.5. Core voltage setting 0.
57            LPM35CoreVoltageSetting0 = 10,
58            /// LPM4.5
59            LPM45 = 12
60        ],
61        /// Current Power Mode
62        CPM OFFSET(8) NUMBITS(6) [
63            /// LDO based Active Mode at Core voltage setting 0.
64            LDOBasedActiveModeAtCoreVoltageSetting0 = 0,
65            /// LDO based Active Mode at Core voltage setting 1.
66            LDOBasedActiveModeAtCoreVoltageSetting1 = 1,
67            /// DC-DC based Active Mode at Core voltage setting 0.
68            DCDCBasedActiveModeAtCoreVoltageSetting0 = 4,
69            /// DC-DC based Active Mode at Core voltage setting 1.
70            DCDCBasedActiveModeAtCoreVoltageSetting1 = 5,
71            /// Low-Frequency Active Mode at Core voltage setting 0.
72            LowFrequencyActiveModeAtCoreVoltageSetting0 = 8,
73            /// Low-Frequency Active Mode at Core voltage setting 1.
74            LowFrequencyActiveModeAtCoreVoltageSetting1 = 9,
75            /// LDO based LPM0 at Core voltage setting 0.
76            LDOBasedLPM0AtCoreVoltageSetting0 = 16,
77            /// LDO based LPM0 at Core voltage setting 1.
78            LDOBasedLPM0AtCoreVoltageSetting1 = 17,
79            /// DC-DC based LPM0 at Core voltage setting 0.
80            DCDCBasedLPM0AtCoreVoltageSetting0 = 20,
81            /// DC-DC based LPM0 at Core voltage setting 1.
82            DCDCBasedLPM0AtCoreVoltageSetting1 = 21,
83            /// Low-Frequency LPM0 at Core voltage setting 0.
84            LowFrequencyLPM0AtCoreVoltageSetting0 = 24,
85            /// Low-Frequency LPM0 at Core voltage setting 1.
86            LowFrequencyLPM0AtCoreVoltageSetting1 = 25,
87            /// LPM3
88            LPM3 = 32
89        ],
90        /// PCM key
91        PCMKEY OFFSET(16) NUMBITS(16) []
92    ],
93    PCMCTL1 [
94        /// Lock LPM5
95        LOCKLPM5 OFFSET(0) NUMBITS(1) [
96            /// LPMx.5 configuration defaults to reset condition
97            LPMx5ConfigurationDefaultsToResetCondition = 0,
98            /// LPMx.5 configuration remains locked during LPMx.5 entry and exit
99            LPMx5ConfigurationRemainsLockedDuringLPMx5EntryAndExit = 1
100        ],
101        /// Lock Backup
102        LOCKBKUP OFFSET(1) NUMBITS(1) [
103            /// Backup domain configuration defaults to reset condition
104            BackupDomainConfigurationDefaultsToResetCondition = 0,
105            /// Backup domain configuration remains locked during LPM3.5 entry and exit
106            BackupDomainConfigurationRemainsLockedDuringLPM35EntryAndExit = 1
107        ],
108        /// Force LPM entry
109        FORCE_LPM_ENTRY OFFSET(2) NUMBITS(1) [
110            /// PCM aborts LPM3/LPMx.5 transition if the active clock configuration does not mee
111            FORCE_LPM_ENTRY_0 = 0,
112            /// PCM enters LPM3/LPMx.5 after shuting off the clocks forcefully. Application need
113            FORCE_LPM_ENTRY_1 = 1
114        ],
115        /// Power mode request busy flag
116        PMR_BUSY OFFSET(8) NUMBITS(1) [],
117        /// PCM key
118        PCMKEY OFFSET(16) NUMBITS(16) []
119    ],
120    PCMIE [
121        /// LPM invalid transition interrupt enable
122        LPM_INVALID_TR_IE OFFSET(0) NUMBITS(1) [
123            /// Disabled
124            Disabled = 0,
125            /// Enabled
126            Enabled = 1
127        ],
128        /// LPM invalid clock interrupt enable
129        LPM_INVALID_CLK_IE OFFSET(1) NUMBITS(1) [
130            /// Disabled
131            Disabled = 0,
132            /// Enabled
133            Enabled = 1
134        ],
135        /// Active mode invalid transition interrupt enable
136        AM_INVALID_TR_IE OFFSET(2) NUMBITS(1) [
137            /// Disabled
138            Disabled = 0,
139            /// Enabled
140            Enabled = 1
141        ],
142        /// DC-DC error interrupt enable
143        DCDC_ERROR_IE OFFSET(6) NUMBITS(1) [
144            /// Disabled
145            Disabled = 0,
146            /// Enabled
147            Enabled = 1
148        ]
149    ],
150    PCMIFG [
151        /// LPM invalid transition flag
152        LPM_INVALID_TR_IFG OFFSET(0) NUMBITS(1) [],
153        /// LPM invalid clock flag
154        LPM_INVALID_CLK_IFG OFFSET(1) NUMBITS(1) [],
155        /// Active mode invalid transition flag
156        AM_INVALID_TR_IFG OFFSET(2) NUMBITS(1) [],
157        /// DC-DC error flag
158        DCDC_ERROR_IFG OFFSET(6) NUMBITS(1) []
159    ],
160    PCMCLRIFG [
161        /// Clear LPM invalid transition flag
162        CLR_LPM_INVALID_TR_IFG OFFSET(0) NUMBITS(1) [],
163        /// Clear LPM invalid clock flag
164        CLR_LPM_INVALID_CLK_IFG OFFSET(1) NUMBITS(1) [],
165        /// Clear active mode invalid transition flag
166        CLR_AM_INVALID_TR_IFG OFFSET(2) NUMBITS(1) [],
167        /// Clear DC-DC error flag
168        CLR_DCDC_ERROR_IFG OFFSET(6) NUMBITS(1) []
169    ]
170];
171
172pub struct Pcm {
173    registers: StaticRef<PcmRegisters>,
174}
175
176impl Pcm {
177    pub const fn new() -> Pcm {
178        Pcm {
179            registers: PCM_BASE,
180        }
181    }
182    // currently not sure about the interface, so just implement a simple
183    // method for activating AM_LDO_VCORE1 to provide enough power for 48MHz
184    pub fn set_high_power(&self) {
185        while self.registers.ctl1.is_set(PCMCTL1::PMR_BUSY) {}
186        self.registers.ctl0.write(
187            PCMCTL0::PCMKEY.val(PCMKEY) + PCMCTL0::AMR::DCDCBasedActiveModeAtCoreVoltageSetting1,
188        );
189        while self.registers.ctl1.is_set(PCMCTL1::PMR_BUSY) {}
190    }
191}