1use crate::bscif;
15use kernel::utilities::StaticRef;
16use kernel::utilities::registers::interfaces::{Readable, Writeable};
17use kernel::utilities::registers::{
18 FieldValue, ReadOnly, ReadWrite, WriteOnly, register_bitfields, register_structs,
19};
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
81register_structs! {
82 ScifRegisters {
83 (0x000 => ier: WriteOnly<u32, Interrupt::Register>),
84 (0x004 => idr: WriteOnly<u32, Interrupt::Register>),
85 (0x008 => imr: ReadOnly<u32, Interrupt::Register>),
86 (0x00C => isr: ReadOnly<u32, Interrupt::Register>),
87 (0x010 => icr: WriteOnly<u32, Interrupt::Register>),
88 (0x014 => pclksr: ReadOnly<u32, Interrupt::Register>),
89 (0x018 => unlock: WriteOnly<u32, Unlock::Register>),
90 (0x01C => cscr: ReadWrite<u32>),
91 (0x020 => oscctrl0: ReadWrite<u32, Oscillator::Register>),
92 (0x024 => pll0: ReadWrite<u32, PllControl::Register>),
93 (0x028 => dfll0conf: ReadWrite<u32, Dfll::Register>),
94 (0x02C => dfll0val: ReadWrite<u32>),
95 (0x030 => dfll0mul: ReadWrite<u32>),
96 (0x034 => dfll0step: ReadWrite<u32, DfllStep::Register>),
97 (0x038 => dfll0ssg: ReadWrite<u32>),
98 (0x03C => dfll0ratio: ReadOnly<u32>),
99 (0x040 => dfll0sync: WriteOnly<u32>),
100 (0x044 => rccr: ReadWrite<u32>),
101 (0x048 => rcfastcfg: ReadWrite<u32, Rcfast::Register>),
102 (0x04C => rcfastsr: ReadOnly<u32>),
103 (0x050 => rc80mcr: ReadWrite<u32, Rc80m::Register>),
104 (0x054 => _reserved0: [u32; 4]),
105 (0x064 => hrpcr: ReadWrite<u32>),
106 (0x068 => fpcr: ReadWrite<u32>),
107 (0x06C => fpmul: ReadWrite<u32>),
108 (0x070 => fpdiv: ReadWrite<u32>),
109 (0x074 => gcctrl0: ReadWrite<u32, GenericClockControl::Register>),
110 (0x078 => gcctrl1: ReadWrite<u32, GenericClockControl::Register>),
111 (0x07C => gcctrl2: ReadWrite<u32, GenericClockControl::Register>),
112 (0x080 => gcctrl3: ReadWrite<u32, GenericClockControl::Register>),
113 (0x084 => gcctrl4: ReadWrite<u32, GenericClockControl::Register>),
114 (0x088 => gcctrl5: ReadWrite<u32, GenericClockControl::Register>),
115 (0x08C => gcctrl6: ReadWrite<u32, GenericClockControl::Register>),
116 (0x090 => gcctrl7: ReadWrite<u32, GenericClockControl::Register>),
117 (0x094 => gcctrl8: ReadWrite<u32, GenericClockControl::Register>),
118 (0x098 => gcctrl9: ReadWrite<u32, GenericClockControl::Register>),
119 (0x09C => gcctrl10: ReadWrite<u32, GenericClockControl::Register>),
120 (0x0A0 => gcctrl11: ReadWrite<u32, GenericClockControl::Register>),
121 (0x0A4 => @END),
122 }
123}
124
125register_bitfields![u32,
126 Interrupt [
127 RCFASTLOCKLOST 14,
128 RCFASTLOCK 13,
129 PLL0LOCKLOST 7,
130 PLL0LOCK 6,
131 DFLL0RCS 4,
132 DFLL0RDY 3,
133 DFLL0LOCKF 2,
134 DFLL0LOCKC 1,
135 OSC0RDY 0
136 ],
137 Unlock [
138 KEY OFFSET(24) NUMBITS(8) [],
139 ADDR OFFSET(0) NUMBITS(10) []
140 ],
141 Oscillator [
142 OSCEN OFFSET(16) NUMBITS(1) [],
143 STARTUP OFFSET(8) NUMBITS(4) [
144 Cycles64 = 1,
145 Cycles1024 = 14
146 ],
147 AGC OFFSET(3) NUMBITS(1) [],
148 GAIN OFFSET(1) NUMBITS(2) [
149 G0 = 0, G1 = 1, G2 = 2, G3 = 3, G4 = 4
150 ],
151 MODE OFFSET(0) NUMBITS(1) [
152 External = 0,
153 Crystal = 1
154 ]
155 ],
156 Dfll [
157 CALIB OFFSET(24) NUMBITS(4) [],
158 FCD OFFSET(23) NUMBITS(1) [],
159 RANGE OFFSET(16) NUMBITS(2) [],
160 QLDIS OFFSET(6) NUMBITS(1) [],
161 CCDIS OFFSET(5) NUMBITS(1) [],
162 LLAW OFFSET(3) NUMBITS(1) [],
163 STABLE OFFSET(2) NUMBITS(1) [],
164 MODE OFFSET(1) NUMBITS(1) [
165 OpenLoop = 0,
166 ClosedLoop = 1
167 ],
168 EN OFFSET(0) NUMBITS(1) []
169 ],
170 DfllStep [
171 CSTEP OFFSET(16) NUMBITS(5) [],
172 FSTEP OFFSET(0) NUMBITS(8) []
173 ],
174 GenericClockControl [
175 DIV OFFSET(16) NUMBITS(16) [],
176 OCSEL OFFSET(8) NUMBITS(5) [
177 ],
179 DIVEN OFFSET(1) NUMBITS(1) [],
180 CEN OFFSET(0) NUMBITS(1) []
181 ],
182 PllControl [
183 PLLCOUNT OFFSET(24) NUMBITS(6) [
184 Max = 0x3F
185 ],
186 PLLMUL OFFSET(16) NUMBITS(4) [],
187 PLLDIV OFFSET(8) NUMBITS(4) [],
188 PLLOSC OFFSET(1) NUMBITS(2) [
189 OSC0 = 0,
190 GCLK9 = 1
191 ],
192 PLLOPT OFFSET(3) NUMBITS(3) [
193 DivideBy2 = 2
194 ],
197 PLLEN OFFSET(0) NUMBITS(1) []
198 ],
199 Rcfast [
200 CALIB OFFSET(16) NUMBITS(7) [],
201 LOCKMARGIN OFFSET(12) NUMBITS(4) [],
202 FRANGE OFFSET(8) NUMBITS(2) [
203 Range4MHz = 0,
204 Range8MHz = 1,
205 Range12MHz = 2
206 ],
207 FCD OFFSET(7) NUMBITS(1) [],
208 NBPERIODS OFFSET(4) NUMBITS(3) [],
209 JITMODE OFFSET(2) NUMBITS(1) [],
210 TUNEEN OFFSET(1) NUMBITS(1) [],
211 EN OFFSET(0) NUMBITS(1) []
212 ],
213 Rc80m [
214 EN OFFSET(0) NUMBITS(1) []
215 ]
216];
217
218const SCIF: StaticRef<ScifRegisters> =
219 unsafe { StaticRef::new(0x400E0800 as *const ScifRegisters) };
220
221#[repr(usize)]
222pub enum Clock {
223 ClockRCSys = 0,
224 ClockOsc32 = 1,
225 ClockAPB = 2,
226 ClockGclk2 = 3,
227 Clock1K = 4,
228}
229
230pub fn unlock(register: Register) {
231 SCIF.unlock
232 .write(Unlock::KEY.val(0xAA) + Unlock::ADDR.val(register as u32));
233}
234
235pub fn oscillator_enable(internal: bool) {
236 let mode = if internal {
237 Oscillator::MODE::Crystal
238 } else {
239 Oscillator::MODE::External
240 };
241 unlock(Register::OSCCTRL0);
242 SCIF.oscctrl0.write(Oscillator::OSCEN::SET + mode);
243}
244
245pub fn oscillator_disable() {
246 unlock(Register::OSCCTRL0);
247 SCIF.oscctrl0.write(Oscillator::OSCEN::CLEAR);
248}
249
250pub fn setup_dfll_rc32k_48mhz() {
251 fn wait_dfll0_ready() {
252 while !SCIF.pclksr.is_set(Interrupt::DFLL0RDY) {}
253 }
254
255 if !SCIF.dfll0conf.is_set(Dfll::EN) || !SCIF.pclksr.is_set(Interrupt::DFLL0LOCKF) {
257 if !bscif::rc32k_enabled() {
259 bscif::enable_rc32k();
260 }
261
262 SCIF.dfll0sync.set(0x01);
269 wait_dfll0_ready();
270
271 let scif_dfll0conf = SCIF.dfll0conf.get();
274 let new_config_fields = Dfll::EN::SET + Dfll::MODE::ClosedLoop + Dfll::RANGE.val(2);
276 let scif_dfll0conf_new = new_config_fields.modify(scif_dfll0conf);
279
280 SCIF.gcctrl0.write(
282 GenericClockControl::CEN::SET
283 + GenericClockControl::OCSEL.val(ClockSource::RC32K as u32)
284 + GenericClockControl::DIVEN::CLEAR
285 + GenericClockControl::DIV.val(0),
286 );
287
288 unlock(Register::DFLL0CONF);
292 SCIF.dfll0conf.write(Dfll::EN::SET);
293 wait_dfll0_ready();
294
295 unlock(Register::DFLL0STEP);
297 SCIF.dfll0step
298 .write(DfllStep::FSTEP.val(4) + DfllStep::CSTEP.val(4));
299 wait_dfll0_ready();
300
301 unlock(Register::DFLL0MUL);
303 SCIF.dfll0mul.set(1464);
305 wait_dfll0_ready();
306
307 unlock(Register::DFLL0SSG);
309 SCIF.dfll0ssg.set(0);
311 wait_dfll0_ready();
312
313 unlock(Register::DFLL0CONF);
315 SCIF.dfll0conf.set(scif_dfll0conf_new);
317
318 while !SCIF.pclksr.is_set(Interrupt::DFLL0LOCKF) {}
320 }
321}
322
323pub unsafe fn disable_dfll_rc32k() {
324 SCIF.dfll0sync.set(0x01);
326 while !SCIF.pclksr.is_set(Interrupt::DFLL0RDY) {}
327
328 let dfll0conf = SCIF.dfll0conf.extract();
330 unlock(Register::DFLL0CONF);
331 SCIF.dfll0conf.modify_no_read(dfll0conf, Dfll::EN::CLEAR);
332
333 generic_clock_disable(GenericClock::GCLK0);
335
336 while SCIF.dfll0conf.is_set(Dfll::EN) {}
338}
339
340pub unsafe fn setup_osc_16mhz_fast_startup() {
341 unlock(Register::OSCCTRL0);
343 SCIF.oscctrl0.write(
344 Oscillator::OSCEN::SET
345 + Oscillator::STARTUP::Cycles64
346 + Oscillator::GAIN::G4
347 + Oscillator::MODE::Crystal,
348 );
349
350 while !SCIF.pclksr.is_set(Interrupt::OSC0RDY) {}
352}
353
354pub unsafe fn setup_osc_16mhz_slow_startup() {
355 unlock(Register::OSCCTRL0);
357 SCIF.oscctrl0.write(
358 Oscillator::OSCEN::SET
359 + Oscillator::STARTUP::Cycles1024
360 + Oscillator::GAIN::G4
361 + Oscillator::MODE::Crystal,
362 );
363
364 while !SCIF.pclksr.is_set(Interrupt::OSC0RDY) {}
366}
367
368pub unsafe fn disable_osc_16mhz() {
369 let oscctrl0 = SCIF.oscctrl0.extract();
371 unlock(Register::OSCCTRL0);
372 SCIF.oscctrl0
373 .modify_no_read(oscctrl0, Oscillator::OSCEN::CLEAR);
374
375 while SCIF.oscctrl0.is_set(Oscillator::OSCEN) {}
377}
378
379pub unsafe fn setup_pll_osc_48mhz() {
380 unlock(Register::PLL0);
383 SCIF.pll0.write(
384 PllControl::PLLCOUNT::Max
385 + PllControl::PLLMUL.val(5)
386 + PllControl::PLLDIV.val(1)
387 + PllControl::PLLOPT::DivideBy2
388 + PllControl::PLLOSC::OSC0
389 + PllControl::PLLEN::SET,
390 );
391
392 while !SCIF.pclksr.is_set(Interrupt::PLL0LOCK) {}
394}
395
396pub unsafe fn disable_pll() {
397 let pll0 = SCIF.pll0.extract();
399 unlock(Register::PLL0);
400 SCIF.pll0.modify_no_read(pll0, PllControl::PLLEN::CLEAR);
401
402 while SCIF.pll0.is_set(PllControl::PLLEN) {}
404}
405
406pub unsafe fn setup_rc_80mhz() {
407 let rc80mcr = SCIF.rc80mcr.extract();
409 unlock(Register::RC80MCR);
410 SCIF.rc80mcr.modify_no_read(rc80mcr, Rc80m::EN::SET);
411
412 while !SCIF.rc80mcr.is_set(Rc80m::EN) {}
414}
415
416pub unsafe fn disable_rc_80mhz() {
417 let rc80mcr = SCIF.rc80mcr.extract();
419 unlock(Register::RC80MCR);
420 SCIF.rc80mcr.modify_no_read(rc80mcr, Rc80m::EN::CLEAR);
421
422 while SCIF.rc80mcr.is_set(Rc80m::EN) {}
424}
425
426pub unsafe fn setup_rcfast_4mhz() {
427 let rcfastcfg = SCIF.rcfastcfg.extract();
429 unlock(Register::RCFASTCFG);
430 SCIF.rcfastcfg.modify_no_read(
431 rcfastcfg,
432 Rcfast::FRANGE::Range4MHz + Rcfast::TUNEEN::CLEAR + Rcfast::EN::SET,
433 );
434
435 while !SCIF.rcfastcfg.is_set(Rcfast::EN) {}
437}
438
439pub unsafe fn setup_rcfast_8mhz() {
440 let rcfastcfg = SCIF.rcfastcfg.extract();
442 unlock(Register::RCFASTCFG);
443 SCIF.rcfastcfg.modify_no_read(
444 rcfastcfg,
445 Rcfast::FRANGE::Range8MHz + Rcfast::TUNEEN::CLEAR + Rcfast::EN::SET,
446 );
447
448 while !SCIF.rcfastcfg.is_set(Rcfast::EN) {}
450}
451
452pub unsafe fn setup_rcfast_12mhz() {
453 let rcfastcfg = SCIF.rcfastcfg.extract();
455 unlock(Register::RCFASTCFG);
456 SCIF.rcfastcfg.modify_no_read(
457 rcfastcfg,
458 Rcfast::FRANGE::Range12MHz + Rcfast::TUNEEN::CLEAR + Rcfast::EN::SET,
459 );
460
461 while !SCIF.rcfastcfg.is_set(Rcfast::EN) {}
463}
464
465pub unsafe fn disable_rcfast() {
466 let rcfastcfg = SCIF.rcfastcfg.extract();
468 unlock(Register::RCFASTCFG);
469 SCIF.rcfastcfg.modify_no_read(rcfastcfg, Rcfast::EN::CLEAR);
470
471 while SCIF.rcfastcfg.is_set(Rcfast::EN) {}
473}
474
475pub fn generic_clock_disable(clock: GenericClock) {
476 generic_clock_control_write(clock, GenericClockControl::CEN::CLEAR);
477}
478
479pub fn generic_clock_enable(clock: GenericClock, source: ClockSource) {
480 generic_clock_control_write(
481 clock,
482 GenericClockControl::OCSEL.val(source as u32) + GenericClockControl::CEN::SET,
483 );
484}
485
486pub fn generic_clock_enable_divided(clock: GenericClock, source: ClockSource, divider: u16) {
489 generic_clock_control_write(
490 clock,
491 GenericClockControl::OCSEL.val(source as u32)
492 + GenericClockControl::DIVEN::SET
493 + GenericClockControl::DIV.val(divider as u32)
494 + GenericClockControl::CEN::SET,
495 );
496}
497
498fn generic_clock_control_write(
499 clock: GenericClock,
500 val: FieldValue<u32, GenericClockControl::Register>,
501) {
502 match clock {
503 GenericClock::GCLK0 => SCIF.gcctrl0.write(val),
504 GenericClock::GCLK1 => SCIF.gcctrl1.write(val),
505 GenericClock::GCLK2 => SCIF.gcctrl2.write(val),
506 GenericClock::GCLK3 => SCIF.gcctrl3.write(val),
507 GenericClock::GCLK4 => SCIF.gcctrl4.write(val),
508 GenericClock::GCLK5 => SCIF.gcctrl5.write(val),
509 GenericClock::GCLK6 => SCIF.gcctrl6.write(val),
510 GenericClock::GCLK7 => SCIF.gcctrl7.write(val),
511 GenericClock::GCLK8 => SCIF.gcctrl8.write(val),
512 GenericClock::GCLK9 => SCIF.gcctrl9.write(val),
513 GenericClock::GCLK10 => SCIF.gcctrl10.write(val),
514 GenericClock::GCLK11 => SCIF.gcctrl11.write(val),
515 }
516}