Skip to main content

sam4l/
bscif.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//! Implementation of the Backup System Control Interface (BSCIF) peripheral.
6
7use kernel::utilities::StaticRef;
8use kernel::utilities::registers::interfaces::{Readable, Writeable};
9use kernel::utilities::registers::{
10    ReadOnly, ReadWrite, WriteOnly, register_bitfields, register_structs,
11};
12
13register_structs! {
14    BscifRegisters {
15        (0x000 => ier: WriteOnly<u32, Interrupt::Register>),
16        (0x004 => idr: WriteOnly<u32, Interrupt::Register>),
17        (0x008 => imr: ReadOnly<u32, Interrupt::Register>),
18        (0x00C => isr: ReadOnly<u32, Interrupt::Register>),
19        (0x010 => icr: WriteOnly<u32, Interrupt::Register>),
20        (0x014 => pclksr: ReadOnly<u32, PowerClocksStatus::Register>),
21        (0x018 => unlock: WriteOnly<u32, Unlock::Register>),
22        (0x01C => _reserved0: u32),
23        (0x020 => oscctrl32: ReadWrite<u32, Oscillator32Control::Register>),
24        (0x024 => rc32kcr: ReadWrite<u32, RC32Control::Register>),
25        (0x028 => rc32ktune: ReadWrite<u32, RC32kTuning::Register>),
26        (0x02C => bod33ctrl: ReadWrite<u32, BodControl::Register>),
27        (0x030 => bod33level: ReadWrite<u32, BodLevel::Register>),
28        (0x034 => bod33sampling: ReadWrite<u32, BodSamplingControl::Register>),
29        (0x038 => bod18ctrl: ReadWrite<u32, BodControl::Register>),
30        (0x03C => bot18level: ReadWrite<u32, BodLevel::Register>),
31        (0x040 => bod18sampling: ReadWrite<u32, BodSamplingControl::Register>),
32        (0x044 => vregcr: ReadWrite<u32, VoltageRegulatorConfig::Register>),
33        (0x048 => _reserved1: [u32; 4]),
34        (0x058 => rc1mcr: ReadWrite<u32, RC1MClockConfig::Register>),
35        (0x05C => _reserved2: u32),
36        (0x060 => bgctrl: ReadWrite<u32, BandgapControl::Register>),
37        (0x064 => bgsr: ReadOnly<u32, BandgapStatus::Register>),
38        (0x068 => _reserved3: [u32; 4]),
39        (0x078 => br0: ReadOnly<u32, Backup::Register>),
40        (0x07C => br1: ReadOnly<u32, Backup::Register>),
41        (0x080 => br2: ReadOnly<u32, Backup::Register>),
42        (0x084 => br3: ReadOnly<u32, Backup::Register>),
43        (0x088 => @END),
44    }
45}
46
47register_bitfields![u32,
48    Interrupt [
49        LPBGRDY 12,
50        VREGOK 10,
51        SSWRDY 9,
52        BOD18SYNRDY 8,
53        BOD33SYNRDY 7,
54        BOD18DET 6,
55        BOD33DET 5,
56        RC32SAT 4,
57        RC32KREFE 3,
58        RC32KLOCK 2,
59        RC32KRDY 1,
60        OSC32RDY 0
61    ],
62
63    PowerClocksStatus [
64        LPBGRDY 12,
65        RC1MRDY 11,
66        VREGOK 10,
67        SSWRDY 9,
68        BOD18SYNRDY 8,
69        BOD33SYNRDY 7,
70        BOD18DET 6,
71        BOD33DET 5,
72        RC32SAT 4,
73        RC32KREFE 3,
74        RC32KLOCK 2,
75        RC32KRDY 1,
76        OSC32RDY 0
77    ],
78
79    Unlock [
80        /// Unlock Key
81        KEY OFFSET(24) NUMBITS(8) [],
82        /// Unlock Address
83        ADDR OFFSET(0) NUMBITS(10) []
84    ],
85
86    Oscillator32Control [
87        /// Oscillator Start-up Time
88        STARTUP OFFSET(16) NUMBITS(3) [
89            Time0ms = 0,
90            Time1ms = 1,
91            Time72ms = 2,
92            Time143ms = 3,
93            Time570ms = 4,
94            Time1100ms = 5,
95            Time2300ms = 6,
96            Time4600ms = 7
97        ],
98        /// Current Selection
99        SELCURR OFFSET(12) NUMBITS(4) [
100            CrystalCurrent50nA = 0,
101            CrystalCurrent75nA = 1,
102            CrystalCurrent100nA = 2,
103            CrystalCurrent125nA = 3,
104            CrystalCurrent150nA = 4,
105            CrystalCurrent175nA = 5,
106            CrystalCurrent200nA = 6,
107            CrystalCurrent225nA = 7,
108            CrystalCurrent250nA = 8,
109            CrystalCurrent275nA = 9,
110            CrystalCurrent300nA = 10,
111            CrystalCurrent325nA = 11,
112            CrystalCurrent350nA = 12,
113            CrystalCurrent375nA = 13,
114            CrystalCurrent400nA = 14,
115            CrystalCurrent425nA = 15
116        ],
117        /// Oscillator Mode
118        MODE OFFSET(8) NUMBITS(3) [
119            ExternalClock = 0,
120            CrystalMode = 1,
121            AmplitudeCrystalMode = 3,
122            CrystalHighCurrentMode = 4,
123            AmplitudeCrystalHighCurrentMode = 5
124        ],
125        /// 1 KHz output Enable
126        EN1K OFFSET(3) NUMBITS(1) [
127            OutputDisable = 0,
128            OutputEnable = 1
129        ],
130        /// 32 KHz output Enable
131        EN32K OFFSET(2) NUMBITS(1) [
132            OutputDisable = 0,
133            OutputEnable = 1
134        ],
135        /// 32 KHz Oscillator Enable
136        OSC32EN OFFSET(0) NUMBITS(1) [
137            OscillatorDisable = 0,
138            OscillatorEnable = 1
139        ]
140    ],
141
142    RC32Control [
143        /// Flash calibration done
144        FCD OFFSET(7) NUMBITS(1) [
145            ReloadCalib = 0,
146            KeepCalib = 1
147        ],
148        /// Reference select
149        REF OFFSET(5) NUMBITS(1) [
150            Osc32kReference = 0,
151            GclkReference = 1
152        ],
153        /// Mode Selection
154        MODE OFFSET(4) NUMBITS(1) [
155            OpenLoop = 0,
156            ClosedLoop = 1
157        ],
158        /// Enable 1 kHz output
159        EN1K OFFSET(3) NUMBITS(1) [
160            OutputDisable = 0,
161            OutputEnable = 1
162        ],
163        /// Enable 32 KHz output
164        EN32K OFFSET(2) NUMBITS(1) [
165            OutputDisable = 0,
166            OutputEnable = 1
167        ],
168        /// Temperature Compensation Enable
169        TCEN OFFSET(1) NUMBITS(1) [
170            NotTempCompensated = 0,
171            TempCompensated = 1
172        ],
173        /// Enable as Generic clock source
174        EN OFFSET(0) NUMBITS(1) [
175            GclkSourceDisable = 0,
176            GclkSourceEnable = 1
177        ]
178    ],
179
180    RC32kTuning [
181        /// Coarse Value
182        COARSE OFFSET(16) NUMBITS(7) [],
183        /// Fine Value
184        FINE OFFSET(0) NUMBITS(6) []
185    ],
186
187    BodControl [
188        /// BOD Control Register Store Final Value
189        SFV OFFSET(31) NUMBITS(1) [
190            NotLocked = 0,
191            Locked = 1
192        ],
193        /// BOD Fuse Calibration Done
194        FCD OFFSET(30) NUMBITS(1) [
195            RedoFlashCalibration = 0,
196            DoNotRedoFlashCalibration = 1
197        ],
198        /// Operation modes
199        MODE OFFSET(16) NUMBITS(1) [
200            Continuous = 0,
201            Sampling = 1
202        ],
203        /// Action
204        ACTION OFFSET(8) NUMBITS(2) [
205            No = 0,
206            Reset = 1,
207            Interrupt = 2
208        ],
209        /// BOD Hysteresis
210        HYST OFFSET(1) NUMBITS(1) [
211            No = 0,
212            Enabled = 1
213        ],
214        /// Enable
215        EN OFFSET(0) NUMBITS(1) [
216            Disabled = 0,
217            Enabled = 1
218        ]
219    ],
220
221    BodSamplingControl [
222        /// Prescaler Select
223        PSEL OFFSET(8) NUMBITS(4) [],
224        /// Clock Source Select
225        CSSEL OFFSET(1) NUMBITS(1) [
226            Rcsys = 0,
227            Ck32k = 1
228        ],
229        /// Clock Enable
230        CEN OFFSET(0) NUMBITS(1) [
231            Stop = 0,
232            Start = 1
233        ]
234    ],
235
236    BodLevel [
237        /// BOD Threshold Range
238        RANGE OFFSET(31) NUMBITS(1) [
239            Standard = 0,
240            Low = 1
241        ],
242        /// BOD Value
243        VAL OFFSET(0) NUMBITS(6) []
244    ],
245
246    VoltageRegulatorConfig [
247        /// Store Final Value
248        SFV OFFSET(31) NUMBITS(1) [
249            ReadWrite = 0,
250            ReadOnly = 1
251        ],
252        /// Stop Switching On Event Enable
253        SSWEVT OFFSET(10) NUMBITS(1) [
254            NotPeripheralControl = 0,
255            PeripheralControl = 1
256        ],
257        /// Stop Switching
258        SSW OFFSET(9) NUMBITS(1) [
259            NotStop = 0,
260            Stop = 1
261        ],
262        /// Spread Spectrum Generator Enable
263        SSG OFFSET(8) NUMBITS(1) [
264            SpreadSpectrumDisable = 0,
265            SpreadSpectrumEnable = 1
266        ],
267        /// Voltage Regulator disable
268        DIS OFFSET(0) NUMBITS(1) [
269            VoltageRegulatorDisable = 0,
270            VoltageRegulatorEnable = 1
271        ]
272    ],
273
274    RC1MClockConfig [
275        /// 1MHz RC Osc Calibration
276        CLKCAL OFFSET(8) NUMBITS(5) [],
277        /// Flash Calibration Done
278        FCD OFFSET(7) NUMBITS(1) [
279            RedoFlashCalibration = 0,
280            DoNotRedoFlashCalibration = 1
281        ],
282        /// 1MHz RC Osc Clock Output Enable
283        CLKOEN OFFSET(0) NUMBITS(1) [
284            NotOutput = 0,
285            Output = 1
286        ]
287    ],
288
289    BandgapControl [
290        /// ADC Input Selection
291        ADCISEL OFFSET(0) NUMBITS(2) [
292            NoConnection = 0,
293            ADCVoltageReference = 2
294        ]
295    ],
296
297    BandgapStatus [
298        /// Voltage Reference Used by the System
299        VREF OFFSET(18) NUMBITS(2) [
300            BothUsed = 0,
301            BandgapUsed = 1,
302            LowPowerBandgapUsed = 2,
303            NeitherUsed = 3
304        ],
305        /// Low Power Bandgap Voltage Reference Ready
306        LPBGRDY OFFSET(17) NUMBITS(1) [
307            NotReady = 0,
308            Ready = 1
309        ],
310        /// Bandgap Voltage Reference Ready
311        BGRDY OFFSET(16) NUMBITS(1) [
312            NotReady = 0,
313            Ready = 1
314        ],
315        /// Bandgap Buffer Ready
316        BGBUFRDY OFFSET(0) NUMBITS(8) [
317            NotReady = 0,
318            Ready = 1
319        ]
320    ],
321
322    Backup [
323        DATA OFFSET(0) NUMBITS(32) []
324    ]
325];
326
327const BSCIF: StaticRef<BscifRegisters> =
328    unsafe { StaticRef::new(0x400F0400 as *const BscifRegisters) };
329
330/// Setup the internal 32kHz RC oscillator.
331pub fn enable_rc32k() {
332    let rc32kcr = BSCIF.rc32kcr.extract();
333    // Unlock the BSCIF::RC32KCR register
334    BSCIF
335        .unlock
336        .write(Unlock::KEY.val(0xAA) + Unlock::ADDR.val(0x24));
337    // Write the BSCIF::RC32KCR register.
338    // Enable the generic clock source, the temperature compensation, and the
339    // 32k output.
340    BSCIF.rc32kcr.modify_no_read(
341        rc32kcr,
342        RC32Control::EN32K::OutputEnable
343            + RC32Control::TCEN::TempCompensated
344            + RC32Control::EN::GclkSourceEnable,
345    );
346    // Wait for it to be ready, although it feels like this won't do anything
347    while !BSCIF.rc32kcr.is_set(RC32Control::EN) {}
348
349    // Load magic calibration value for the 32KHz RC oscillator
350    //
351    // Unlock the BSCIF::RC32KTUNE register
352    BSCIF
353        .unlock
354        .write(Unlock::KEY.val(0xAA) + Unlock::ADDR.val(0x28));
355    // Write the BSCIF::RC32KTUNE register
356    BSCIF
357        .rc32ktune
358        .write(RC32kTuning::COARSE.val(0x1d) + RC32kTuning::FINE.val(0x15));
359}
360
361pub fn rc32k_enabled() -> bool {
362    BSCIF.rc32kcr.is_set(RC32Control::EN)
363}
364
365pub fn setup_rc_1mhz() {
366    let rc1mcr = BSCIF.rc1mcr.extract();
367    // Unlock the BSCIF::RC32KCR register
368    BSCIF
369        .unlock
370        .write(Unlock::KEY.val(0xAA) + Unlock::ADDR.val(0x58));
371    // Enable the RC1M
372    BSCIF
373        .rc1mcr
374        .modify_no_read(rc1mcr, RC1MClockConfig::CLKOEN::Output);
375
376    // Wait for the RC1M to be enabled
377    while !BSCIF.rc1mcr.is_set(RC1MClockConfig::CLKOEN) {}
378}
379
380pub unsafe fn disable_rc_1mhz() {
381    let rc1mcr = BSCIF.rc1mcr.extract();
382    // Unlock the BSCIF::RC32KCR register
383    BSCIF
384        .unlock
385        .write(Unlock::KEY.val(0xAA) + Unlock::ADDR.val(0x58));
386    // Disable the RC1M
387    BSCIF
388        .rc1mcr
389        .modify_no_read(rc1mcr, RC1MClockConfig::CLKOEN::NotOutput);
390
391    // Wait for the RC1M to be disabled
392    while BSCIF.rc1mcr.is_set(RC1MClockConfig::CLKOEN) {}
393}