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