1use crate::bscif;
15use kernel::utilities::registers::interfaces::{Readable, Writeable};
16use kernel::utilities::registers::{
17    register_bitfields, FieldValue, ReadOnly, ReadWrite, WriteOnly,
18};
19use kernel::utilities::StaticRef;
20
21pub enum Register {
22    IER = 0x00,
23    IDR = 0x04,
24    IMR = 0x08,
25    ISR = 0x0C,
26    ICR = 0x10,
27    PCLKSR = 0x14,
28    UNLOCK = 0x18,
29    CSCR = 0x1C,
30    OSCCTRL0 = 0x20,
31    PLL0 = 0x24,
32    DFLL0CONF = 0x28,
33    DFLL0MUL = 0x30,
34    DFLL0STEP = 0x34,
35    DFLL0SSG = 0x38,
36    RCFASTCFG = 0x48,
37    RC80MCR = 0x50,
38}
39
40#[allow(non_camel_case_types)]
41pub enum ClockSource {
42    RCSYS = 0,
43    OSC32K = 1,
44    DFLL0 = 2,
45    OSC0 = 3,
46    RC80M = 4,
47    RCFAST = 5,
48    RC1M = 6,
49    CLK_CPU = 7,
50    CLK_HSB = 8,
51    CLK_PBA = 9,
52    CLK_PBB = 10,
53    CLK_PBC = 11,
54    CLK_PBD = 12,
55    RC32K = 13,
56    RESERVED1 = 14,
57    CLK_1K = 15,
58    PLL0 = 16,
59    HRP = 17,
60    FP = 18,
61    GCLK_IN0 = 19,
62    GCLK_IN1 = 20,
63    GCLK11 = 21,
64}
65
66pub enum GenericClock {
67    GCLK0,
68    GCLK1,
69    GCLK2,
70    GCLK3,
71    GCLK4,
72    GCLK5,
73    GCLK6,
74    GCLK7,
75    GCLK8,
76    GCLK9,
77    GCLK10,
78    GCLK11,
79}
80
81#[repr(C)]
82struct ScifRegisters {
83    ier: WriteOnly<u32, Interrupt::Register>,
84    idr: WriteOnly<u32, Interrupt::Register>,
85    imr: ReadOnly<u32, Interrupt::Register>,
86    isr: ReadOnly<u32, Interrupt::Register>,
87    icr: WriteOnly<u32, Interrupt::Register>,
88    pclksr: ReadOnly<u32, Interrupt::Register>,
89    unlock: WriteOnly<u32, Unlock::Register>,
90    cscr: ReadWrite<u32>,
91    oscctrl0: ReadWrite<u32, Oscillator::Register>,
92    pll0: ReadWrite<u32, PllControl::Register>,
93    dfll0conf: ReadWrite<u32, Dfll::Register>,
94    dfll0val: ReadWrite<u32>,
95    dfll0mul: ReadWrite<u32>,
96    dfll0step: ReadWrite<u32, DfllStep::Register>,
97    dfll0ssg: ReadWrite<u32>,
98    dfll0ratio: ReadOnly<u32>,
99    dfll0sync: WriteOnly<u32>,
100    rccr: ReadWrite<u32>,
101    rcfastcfg: ReadWrite<u32, Rcfast::Register>,
102    rcfastsr: ReadOnly<u32>,
103    rc80mcr: ReadWrite<u32, Rc80m::Register>,
104    _reserved0: [u32; 4],
105    hrpcr: ReadWrite<u32>,
106    fpcr: ReadWrite<u32>,
107    fpmul: ReadWrite<u32>,
108    fpdiv: ReadWrite<u32>,
109    gcctrl0: ReadWrite<u32, GenericClockControl::Register>,
110    gcctrl1: ReadWrite<u32, GenericClockControl::Register>,
111    gcctrl2: ReadWrite<u32, GenericClockControl::Register>,
112    gcctrl3: ReadWrite<u32, GenericClockControl::Register>,
113    gcctrl4: ReadWrite<u32, GenericClockControl::Register>,
114    gcctrl5: ReadWrite<u32, GenericClockControl::Register>,
115    gcctrl6: ReadWrite<u32, GenericClockControl::Register>,
116    gcctrl7: ReadWrite<u32, GenericClockControl::Register>,
117    gcctrl8: ReadWrite<u32, GenericClockControl::Register>,
118    gcctrl9: ReadWrite<u32, GenericClockControl::Register>,
119    gcctrl10: ReadWrite<u32, GenericClockControl::Register>,
120    gcctrl11: ReadWrite<u32, GenericClockControl::Register>,
121    }
123
124register_bitfields![u32,
125    Interrupt [
126        RCFASTLOCKLOST 14,
127        RCFASTLOCK 13,
128        PLL0LOCKLOST 7,
129        PLL0LOCK 6,
130        DFLL0RCS 4,
131        DFLL0RDY 3,
132        DFLL0LOCKF 2,
133        DFLL0LOCKC 1,
134        OSC0RDY 0
135    ],
136    Unlock [
137        KEY OFFSET(24) NUMBITS(8) [],
138        ADDR OFFSET(0) NUMBITS(10) []
139    ],
140    Oscillator [
141        OSCEN OFFSET(16) NUMBITS(1) [],
142        STARTUP OFFSET(8) NUMBITS(4) [
143            Cycles64 = 1,
144            Cycles1024 = 14
145        ],
146        AGC OFFSET(3) NUMBITS(1) [],
147        GAIN OFFSET(1) NUMBITS(2) [
148            G0 = 0, G1 = 1, G2 = 2, G3 = 3, G4 = 4
149        ],
150        MODE OFFSET(0) NUMBITS(1) [
151            External = 0,
152            Crystal = 1
153        ]
154    ],
155    Dfll [
156        CALIB OFFSET(24) NUMBITS(4) [],
157        FCD OFFSET(23) NUMBITS(1) [],
158        RANGE OFFSET(16) NUMBITS(2) [],
159        QLDIS OFFSET(6) NUMBITS(1) [],
160        CCDIS OFFSET(5) NUMBITS(1) [],
161        LLAW OFFSET(3) NUMBITS(1) [],
162        STABLE OFFSET(2) NUMBITS(1) [],
163        MODE OFFSET(1) NUMBITS(1) [
164            OpenLoop = 0,
165            ClosedLoop = 1
166        ],
167        EN OFFSET(0) NUMBITS(1) []
168    ],
169    DfllStep [
170        CSTEP OFFSET(16) NUMBITS(5) [],
171        FSTEP OFFSET(0) NUMBITS(8) []
172    ],
173    GenericClockControl [
174        DIV OFFSET(16) NUMBITS(16) [],
175        OCSEL OFFSET(8) NUMBITS(5) [
176            ],
178        DIVEN OFFSET(1) NUMBITS(1) [],
179        CEN OFFSET(0) NUMBITS(1) []
180    ],
181    PllControl [
182        PLLCOUNT OFFSET(24) NUMBITS(6) [
183            Max = 0x3F
184        ],
185        PLLMUL OFFSET(16) NUMBITS(4) [],
186        PLLDIV OFFSET(8) NUMBITS(4) [],
187        PLLOSC OFFSET(1) NUMBITS(2) [
188            OSC0 = 0,
189            GCLK9 = 1
190        ],
191        PLLOPT OFFSET(3) NUMBITS(3) [
192            DivideBy2 = 2
193            ],
196        PLLEN OFFSET(0) NUMBITS(1) []
197    ],
198    Rcfast [
199        CALIB OFFSET(16) NUMBITS(7) [],
200        LOCKMARGIN OFFSET(12) NUMBITS(4) [],
201        FRANGE OFFSET(8) NUMBITS(2) [
202            Range4MHz = 0,
203            Range8MHz = 1,
204            Range12MHz = 2
205        ],
206        FCD OFFSET(7) NUMBITS(1) [],
207        NBPERIODS OFFSET(4) NUMBITS(3) [],
208        JITMODE OFFSET(2) NUMBITS(1) [],
209        TUNEEN OFFSET(1) NUMBITS(1) [],
210        EN OFFSET(0) NUMBITS(1) []
211    ],
212    Rc80m [
213        EN OFFSET(0) NUMBITS(1) []
214    ]
215];
216
217const SCIF: StaticRef<ScifRegisters> =
218    unsafe { StaticRef::new(0x400E0800 as *const ScifRegisters) };
219
220#[repr(usize)]
221pub enum Clock {
222    ClockRCSys = 0,
223    ClockOsc32 = 1,
224    ClockAPB = 2,
225    ClockGclk2 = 3,
226    Clock1K = 4,
227}
228
229pub fn unlock(register: Register) {
230    SCIF.unlock
231        .write(Unlock::KEY.val(0xAA) + Unlock::ADDR.val(register as u32));
232}
233
234pub fn oscillator_enable(internal: bool) {
235    let mode = if internal {
236        Oscillator::MODE::Crystal
237    } else {
238        Oscillator::MODE::External
239    };
240    unlock(Register::OSCCTRL0);
241    SCIF.oscctrl0.write(Oscillator::OSCEN::SET + mode);
242}
243
244pub fn oscillator_disable() {
245    unlock(Register::OSCCTRL0);
246    SCIF.oscctrl0.write(Oscillator::OSCEN::CLEAR);
247}
248
249pub fn setup_dfll_rc32k_48mhz() {
250    fn wait_dfll0_ready() {
251        while !SCIF.pclksr.is_set(Interrupt::DFLL0RDY) {}
252    }
253
254    if !SCIF.dfll0conf.is_set(Dfll::EN) || !SCIF.pclksr.is_set(Interrupt::DFLL0LOCKF) {
256        if !bscif::rc32k_enabled() {
258            bscif::enable_rc32k();
259        }
260
261        SCIF.dfll0sync.set(0x01);
268        wait_dfll0_ready();
269
270        let scif_dfll0conf = SCIF.dfll0conf.get();
273        let new_config_fields = Dfll::EN::SET + Dfll::MODE::ClosedLoop + Dfll::RANGE.val(2);
275        let scif_dfll0conf_new = new_config_fields.modify(scif_dfll0conf);
278
279        SCIF.gcctrl0.write(
281            GenericClockControl::CEN::SET
282                + GenericClockControl::OCSEL.val(ClockSource::RC32K as u32)
283                + GenericClockControl::DIVEN::CLEAR
284                + GenericClockControl::DIV.val(0),
285        );
286
287        unlock(Register::DFLL0CONF);
291        SCIF.dfll0conf.write(Dfll::EN::SET);
292        wait_dfll0_ready();
293
294        unlock(Register::DFLL0STEP);
296        SCIF.dfll0step
297            .write(DfllStep::FSTEP.val(4) + DfllStep::CSTEP.val(4));
298        wait_dfll0_ready();
299
300        unlock(Register::DFLL0MUL);
302        SCIF.dfll0mul.set(1464);
304        wait_dfll0_ready();
305
306        unlock(Register::DFLL0SSG);
308        SCIF.dfll0ssg.set(0);
310        wait_dfll0_ready();
311
312        unlock(Register::DFLL0CONF);
314        SCIF.dfll0conf.set(scif_dfll0conf_new);
316
317        while !SCIF.pclksr.is_set(Interrupt::DFLL0LOCKF) {}
319    }
320}
321
322pub unsafe fn disable_dfll_rc32k() {
323    SCIF.dfll0sync.set(0x01);
325    while !SCIF.pclksr.is_set(Interrupt::DFLL0RDY) {}
326
327    let dfll0conf = SCIF.dfll0conf.extract();
329    unlock(Register::DFLL0CONF);
330    SCIF.dfll0conf.modify_no_read(dfll0conf, Dfll::EN::CLEAR);
331
332    generic_clock_disable(GenericClock::GCLK0);
334
335    while SCIF.dfll0conf.is_set(Dfll::EN) {}
337}
338
339pub unsafe fn setup_osc_16mhz_fast_startup() {
340    unlock(Register::OSCCTRL0);
342    SCIF.oscctrl0.write(
343        Oscillator::OSCEN::SET
344            + Oscillator::STARTUP::Cycles64
345            + Oscillator::GAIN::G4
346            + Oscillator::MODE::Crystal,
347    );
348
349    while !SCIF.pclksr.is_set(Interrupt::OSC0RDY) {}
351}
352
353pub unsafe fn setup_osc_16mhz_slow_startup() {
354    unlock(Register::OSCCTRL0);
356    SCIF.oscctrl0.write(
357        Oscillator::OSCEN::SET
358            + Oscillator::STARTUP::Cycles1024
359            + Oscillator::GAIN::G4
360            + Oscillator::MODE::Crystal,
361    );
362
363    while !SCIF.pclksr.is_set(Interrupt::OSC0RDY) {}
365}
366
367pub unsafe fn disable_osc_16mhz() {
368    let oscctrl0 = SCIF.oscctrl0.extract();
370    unlock(Register::OSCCTRL0);
371    SCIF.oscctrl0
372        .modify_no_read(oscctrl0, Oscillator::OSCEN::CLEAR);
373
374    while SCIF.oscctrl0.is_set(Oscillator::OSCEN) {}
376}
377
378pub unsafe fn setup_pll_osc_48mhz() {
379    unlock(Register::PLL0);
382    SCIF.pll0.write(
383        PllControl::PLLCOUNT::Max
384            + PllControl::PLLMUL.val(5)
385            + PllControl::PLLDIV.val(1)
386            + PllControl::PLLOPT::DivideBy2
387            + PllControl::PLLOSC::OSC0
388            + PllControl::PLLEN::SET,
389    );
390
391    while !SCIF.pclksr.is_set(Interrupt::PLL0LOCK) {}
393}
394
395pub unsafe fn disable_pll() {
396    let pll0 = SCIF.pll0.extract();
398    unlock(Register::PLL0);
399    SCIF.pll0.modify_no_read(pll0, PllControl::PLLEN::CLEAR);
400
401    while SCIF.pll0.is_set(PllControl::PLLEN) {}
403}
404
405pub unsafe fn setup_rc_80mhz() {
406    let rc80mcr = SCIF.rc80mcr.extract();
408    unlock(Register::RC80MCR);
409    SCIF.rc80mcr.modify_no_read(rc80mcr, Rc80m::EN::SET);
410
411    while !SCIF.rc80mcr.is_set(Rc80m::EN) {}
413}
414
415pub unsafe fn disable_rc_80mhz() {
416    let rc80mcr = SCIF.rc80mcr.extract();
418    unlock(Register::RC80MCR);
419    SCIF.rc80mcr.modify_no_read(rc80mcr, Rc80m::EN::CLEAR);
420
421    while SCIF.rc80mcr.is_set(Rc80m::EN) {}
423}
424
425pub unsafe fn setup_rcfast_4mhz() {
426    let rcfastcfg = SCIF.rcfastcfg.extract();
428    unlock(Register::RCFASTCFG);
429    SCIF.rcfastcfg.modify_no_read(
430        rcfastcfg,
431        Rcfast::FRANGE::Range4MHz + Rcfast::TUNEEN::CLEAR + Rcfast::EN::SET,
432    );
433
434    while !SCIF.rcfastcfg.is_set(Rcfast::EN) {}
436}
437
438pub unsafe fn setup_rcfast_8mhz() {
439    let rcfastcfg = SCIF.rcfastcfg.extract();
441    unlock(Register::RCFASTCFG);
442    SCIF.rcfastcfg.modify_no_read(
443        rcfastcfg,
444        Rcfast::FRANGE::Range8MHz + Rcfast::TUNEEN::CLEAR + Rcfast::EN::SET,
445    );
446
447    while !SCIF.rcfastcfg.is_set(Rcfast::EN) {}
449}
450
451pub unsafe fn setup_rcfast_12mhz() {
452    let rcfastcfg = SCIF.rcfastcfg.extract();
454    unlock(Register::RCFASTCFG);
455    SCIF.rcfastcfg.modify_no_read(
456        rcfastcfg,
457        Rcfast::FRANGE::Range12MHz + Rcfast::TUNEEN::CLEAR + Rcfast::EN::SET,
458    );
459
460    while !SCIF.rcfastcfg.is_set(Rcfast::EN) {}
462}
463
464pub unsafe fn disable_rcfast() {
465    let rcfastcfg = SCIF.rcfastcfg.extract();
467    unlock(Register::RCFASTCFG);
468    SCIF.rcfastcfg.modify_no_read(rcfastcfg, Rcfast::EN::CLEAR);
469
470    while SCIF.rcfastcfg.is_set(Rcfast::EN) {}
472}
473
474pub fn generic_clock_disable(clock: GenericClock) {
475    generic_clock_control_write(clock, GenericClockControl::CEN::CLEAR);
476}
477
478pub fn generic_clock_enable(clock: GenericClock, source: ClockSource) {
479    generic_clock_control_write(
480        clock,
481        GenericClockControl::OCSEL.val(source as u32) + GenericClockControl::CEN::SET,
482    );
483}
484
485pub fn generic_clock_enable_divided(clock: GenericClock, source: ClockSource, divider: u16) {
488    generic_clock_control_write(
489        clock,
490        GenericClockControl::OCSEL.val(source as u32)
491            + GenericClockControl::DIVEN::SET
492            + GenericClockControl::DIV.val(divider as u32)
493            + GenericClockControl::CEN::SET,
494    );
495}
496
497fn generic_clock_control_write(
498    clock: GenericClock,
499    val: FieldValue<u32, GenericClockControl::Register>,
500) {
501    match clock {
502        GenericClock::GCLK0 => SCIF.gcctrl0.write(val),
503        GenericClock::GCLK1 => SCIF.gcctrl1.write(val),
504        GenericClock::GCLK2 => SCIF.gcctrl2.write(val),
505        GenericClock::GCLK3 => SCIF.gcctrl3.write(val),
506        GenericClock::GCLK4 => SCIF.gcctrl4.write(val),
507        GenericClock::GCLK5 => SCIF.gcctrl5.write(val),
508        GenericClock::GCLK6 => SCIF.gcctrl6.write(val),
509        GenericClock::GCLK7 => SCIF.gcctrl7.write(val),
510        GenericClock::GCLK8 => SCIF.gcctrl8.write(val),
511        GenericClock::GCLK9 => SCIF.gcctrl9.write(val),
512        GenericClock::GCLK10 => SCIF.gcctrl10.write(val),
513        GenericClock::GCLK11 => SCIF.gcctrl11.write(val),
514    }
515}