]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/protocol/arm_atsam/clks.c
Massdrop keyboard support (#3780)
[qmk_firmware.git] / tmk_core / protocol / arm_atsam / clks.c
1 /*
2 Copyright 2018 Massdrop Inc.
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "arm_atsam_protocol.h"
19
20 #include <string.h>
21
22 volatile clk_t system_clks;
23 volatile uint64_t ms_clk;
24
25 volatile uint8_t us_delay_done;
26
27 const uint32_t sercom_apbbase[] = {(uint32_t)SERCOM0,(uint32_t)SERCOM1,(uint32_t)SERCOM2,(uint32_t)SERCOM3,(uint32_t)SERCOM4,(uint32_t)SERCOM5};
28 const uint8_t sercom_pchan[] = {7, 8, 23, 24, 34, 35};
29
30 #define USE_DPLL_IND    0
31 #define USE_DPLL_DEF    GCLK_SOURCE_DPLL0
32
33 void CLK_oscctrl_init(void)
34 {
35     Oscctrl *posctrl = OSCCTRL;
36     Gclk *pgclk = GCLK;
37
38     DBGC(DC_CLK_OSC_INIT_BEGIN);
39
40     //default setup on por
41     system_clks.freq_dfll = FREQ_DFLL_DEFAULT;
42     system_clks.freq_gclk[0] = system_clks.freq_dfll;
43
44     //configure and startup 16MHz xosc0
45     posctrl->XOSCCTRL[0].bit.ENABLE = 0;
46     posctrl->XOSCCTRL[0].bit.STARTUP = 0xD;
47     posctrl->XOSCCTRL[0].bit.ENALC = 1;
48     posctrl->XOSCCTRL[0].bit.IMULT = 5;
49     posctrl->XOSCCTRL[0].bit.IPTAT = 3;
50     posctrl->XOSCCTRL[0].bit.ONDEMAND = 0;
51     posctrl->XOSCCTRL[0].bit.XTALEN = 1;
52     posctrl->XOSCCTRL[0].bit.ENABLE = 1;
53     while (posctrl->STATUS.bit.XOSCRDY0 == 0) { DBGC(DC_CLK_OSC_INIT_XOSC0_SYNC); }
54     system_clks.freq_xosc0 = FREQ_XOSC0;
55
56     //configure and startup DPLL
57     posctrl->Dpll[USE_DPLL_IND].DPLLCTRLA.bit.ENABLE = 0;
58     while (posctrl->Dpll[USE_DPLL_IND].DPLLSYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_OSC_INIT_DPLL_SYNC_DISABLE); }
59     posctrl->Dpll[USE_DPLL_IND].DPLLCTRLB.bit.REFCLK = 2;              //select XOSC0 (16MHz)
60     posctrl->Dpll[USE_DPLL_IND].DPLLCTRLB.bit.DIV = 7;                 //16 MHz / (2 * (7 + 1)) = 1 MHz
61     posctrl->Dpll[USE_DPLL_IND].DPLLRATIO.bit.LDR = PLL_RATIO;         //1 MHz * (PLL_RATIO(47) + 1) = 48MHz
62     while (posctrl->Dpll[USE_DPLL_IND].DPLLSYNCBUSY.bit.DPLLRATIO) { DBGC(DC_CLK_OSC_INIT_DPLL_SYNC_RATIO); }
63     posctrl->Dpll[USE_DPLL_IND].DPLLCTRLA.bit.ONDEMAND = 0;
64     posctrl->Dpll[USE_DPLL_IND].DPLLCTRLA.bit.ENABLE = 1;
65     while (posctrl->Dpll[USE_DPLL_IND].DPLLSYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_OSC_INIT_DPLL_SYNC_ENABLE); }
66     while (posctrl->Dpll[USE_DPLL_IND].DPLLSTATUS.bit.LOCK == 0) { DBGC(DC_CLK_OSC_INIT_DPLL_WAIT_LOCK); }
67     while (posctrl->Dpll[USE_DPLL_IND].DPLLSTATUS.bit.CLKRDY == 0) { DBGC(DC_CLK_OSC_INIT_DPLL_WAIT_CLKRDY); }
68     system_clks.freq_dpll[0] = (system_clks.freq_xosc0 / 2 / (posctrl->Dpll[USE_DPLL_IND].DPLLCTRLB.bit.DIV + 1)) * (posctrl->Dpll[USE_DPLL_IND].DPLLRATIO.bit.LDR + 1);
69
70     //change gclk0 to DPLL
71     pgclk->GENCTRL[GEN_DPLL0].bit.SRC = USE_DPLL_DEF;
72     while (pgclk->SYNCBUSY.bit.GENCTRL0) { DBGC(DC_CLK_OSC_INIT_GCLK_SYNC_GENCTRL0); }
73
74     system_clks.freq_gclk[0] = system_clks.freq_dpll[0];
75
76     DBGC(DC_CLK_OSC_INIT_COMPLETE);
77 }
78
79 //configure for 1MHz (1 usec timebase)
80 //call CLK_set_gclk_freq(GEN_TC45, FREQ_TC45_DEFAULT);
81 uint32_t CLK_set_gclk_freq(uint8_t gclkn, uint32_t freq)
82 {
83     Gclk *pgclk = GCLK;
84
85     DBGC(DC_CLK_SET_GCLK_FREQ_BEGIN);
86
87     while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_1); }
88     pgclk->GENCTRL[gclkn].bit.SRC = USE_DPLL_DEF;
89     while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_2); }
90     pgclk->GENCTRL[gclkn].bit.DIV = (uint8_t)(system_clks.freq_dpll[0] / freq);
91     while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_3); }
92     pgclk->GENCTRL[gclkn].bit.DIVSEL = 0;
93     while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_4); }
94     pgclk->GENCTRL[gclkn].bit.GENEN = 1;
95     while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_SET_GCLK_FREQ_SYNC_5); }
96     system_clks.freq_gclk[gclkn] = system_clks.freq_dpll[0] / pgclk->GENCTRL[gclkn].bit.DIV;
97
98     DBGC(DC_CLK_SET_GCLK_FREQ_COMPLETE);
99
100     return system_clks.freq_gclk[gclkn];
101 }
102
103 void CLK_init_osc(void)
104 {
105     uint8_t gclkn = GEN_OSC0;
106     Gclk *pgclk = GCLK;
107
108     DBGC(DC_CLK_INIT_OSC_BEGIN);
109
110     while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_1); }
111     pgclk->GENCTRL[gclkn].bit.SRC = GCLK_SOURCE_XOSC0;
112     while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_2); }
113     pgclk->GENCTRL[gclkn].bit.DIV = 1;
114     while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_3); }
115     pgclk->GENCTRL[gclkn].bit.DIVSEL = 0;
116     while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_4); }
117     pgclk->GENCTRL[gclkn].bit.GENEN = 1;
118     while (pgclk->SYNCBUSY.vec.GENCTRL) { DBGC(DC_CLK_INIT_OSC_SYNC_5); }
119     system_clks.freq_gclk[gclkn] = system_clks.freq_xosc0;
120
121     DBGC(DC_CLK_INIT_OSC_COMPLETE);
122 }
123
124 void CLK_reset_time(void)
125 {
126     Tc *ptc4 = TC4;
127     Tc *ptc0 = TC0;
128
129     ms_clk = 0;
130
131     DBGC(DC_CLK_RESET_TIME_BEGIN);
132
133     //stop counters
134     ptc4->COUNT16.CTRLA.bit.ENABLE = 0;
135     while (ptc4->COUNT16.SYNCBUSY.bit.ENABLE) {}
136     ptc0->COUNT32.CTRLA.bit.ENABLE = 0;
137     while (ptc0->COUNT32.SYNCBUSY.bit.ENABLE) {}
138     //zero counters
139     ptc4->COUNT16.COUNT.reg = 0;
140     while (ptc4->COUNT16.SYNCBUSY.bit.COUNT) {}
141     ptc0->COUNT32.COUNT.reg = 0;
142     while (ptc0->COUNT32.SYNCBUSY.bit.COUNT) {}
143     //start counters
144     ptc0->COUNT32.CTRLA.bit.ENABLE = 1;
145     while (ptc0->COUNT32.SYNCBUSY.bit.ENABLE) {}
146     ptc4->COUNT16.CTRLA.bit.ENABLE = 1;
147     while (ptc4->COUNT16.SYNCBUSY.bit.ENABLE) {}
148
149     DBGC(DC_CLK_RESET_TIME_COMPLETE);
150 }
151
152 void TC4_Handler()
153 {
154     if (TC4->COUNT16.INTFLAG.bit.MC0)
155     {
156         TC4->COUNT16.INTFLAG.reg = TC_INTENCLR_MC0;
157         ms_clk++;
158     }
159 }
160
161 void TC5_Handler()
162 {
163     if (TC5->COUNT16.INTFLAG.bit.MC0)
164     {
165         TC5->COUNT16.INTFLAG.reg = TC_INTENCLR_MC0;
166         us_delay_done = 1;
167         TC5->COUNT16.CTRLA.bit.ENABLE = 0;
168         while (TC5->COUNT16.SYNCBUSY.bit.ENABLE) {}
169     }
170 }
171
172 uint32_t CLK_enable_timebase(void)
173 {
174     Gclk *pgclk = GCLK;
175     Mclk *pmclk = MCLK;
176     Tc *ptc4 = TC4;
177     Tc *ptc5 = TC5;
178     Tc *ptc0 = TC0;
179     Evsys *pevsys = EVSYS;
180
181     DBGC(DC_CLK_ENABLE_TIMEBASE_BEGIN);
182
183     //gclk2  highspeed time base
184     CLK_set_gclk_freq(GEN_TC45, FREQ_TC45_DEFAULT);
185     CLK_init_osc();
186
187     //unmask TC4, sourcegclk2 to TC4
188     pmclk->APBCMASK.bit.TC4_ = 1;
189     pgclk->PCHCTRL[TC4_GCLK_ID].bit.GEN = GEN_TC45;
190     pgclk->PCHCTRL[TC4_GCLK_ID].bit.CHEN = 1;
191
192     //unmask TC5 sourcegclk2 to TC5
193     pmclk->APBCMASK.bit.TC5_ = 1;
194     pgclk->PCHCTRL[TC5_GCLK_ID].bit.GEN = GEN_TC45;
195     pgclk->PCHCTRL[TC5_GCLK_ID].bit.CHEN = 1;
196
197     //configure TC4
198     DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_BEGIN);
199     ptc4->COUNT16.CTRLA.bit.ENABLE = 0;
200     while (ptc4->COUNT16.SYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_DISABLE); }
201     ptc4->COUNT16.CTRLA.bit.SWRST = 1;
202     while (ptc4->COUNT16.SYNCBUSY.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_SWRST_1); }
203     while (ptc4->COUNT16.CTRLA.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_SWRST_2); }
204
205     //CTRLA defaults
206     //CTRLB as default, counting up
207     ptc4->COUNT16.CTRLBCLR.reg = 5;
208     while (ptc4->COUNT16.SYNCBUSY.bit.CTRLB) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_CLTRB); }
209     ptc4->COUNT16.CC[0].reg = 999;
210     while (ptc4->COUNT16.SYNCBUSY.bit.CC0) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_SYNC_CC0); }
211     //ptc4->COUNT16.DBGCTRL.bit.DBGRUN = 1;
212
213     //wave mode
214     ptc4->COUNT16.WAVE.bit.WAVEGEN = 1; //MFRQ match frequency mode, toggle each CC match
215     //generate event for next stage
216     ptc4->COUNT16.EVCTRL.bit.MCEO0 = 1;
217
218     NVIC_EnableIRQ(TC4_IRQn);
219     ptc4->COUNT16.INTENSET.bit.MC0 = 1;
220
221     DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_COMPLETE);
222
223     //configure TC5
224     DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_BEGIN);
225     ptc5->COUNT16.CTRLA.bit.ENABLE = 0;
226     while (ptc5->COUNT16.SYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_DISABLE); }
227     ptc5->COUNT16.CTRLA.bit.SWRST = 1;
228     while (ptc5->COUNT16.SYNCBUSY.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_1); }
229     while (ptc5->COUNT16.CTRLA.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_2); }
230
231     //CTRLA defaults
232     //CTRLB as default, counting up
233     ptc5->COUNT16.CTRLBCLR.reg = 5;
234     while (ptc5->COUNT16.SYNCBUSY.bit.CTRLB) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_CLTRB); }
235     //ptc5->COUNT16.DBGCTRL.bit.DBGRUN = 1;
236
237     //wave mode
238     ptc5->COUNT16.WAVE.bit.WAVEGEN = 1; //MFRQ match frequency mode, toggle each CC match
239     //generate event for next stage
240     ptc5->COUNT16.EVCTRL.bit.MCEO0 = 1;
241
242     NVIC_EnableIRQ(TC5_IRQn);
243     ptc5->COUNT16.INTENSET.bit.MC0 = 1;
244
245     DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_COMPLETE);
246
247     //unmask TC0,1, sourcegclk2 to TC0,1
248     pmclk->APBAMASK.bit.TC0_ = 1;
249     pgclk->PCHCTRL[TC0_GCLK_ID].bit.GEN = GEN_TC45;
250     pgclk->PCHCTRL[TC0_GCLK_ID].bit.CHEN = 1;
251
252     pmclk->APBAMASK.bit.TC1_ = 1;
253     pgclk->PCHCTRL[TC1_GCLK_ID].bit.GEN = GEN_TC45;
254     pgclk->PCHCTRL[TC1_GCLK_ID].bit.CHEN = 1;
255
256     //configure TC0
257     DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_BEGIN);
258     ptc0->COUNT32.CTRLA.bit.ENABLE = 0;
259     while (ptc0->COUNT32.SYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_DISABLE); }
260     ptc0->COUNT32.CTRLA.bit.SWRST = 1;
261     while (ptc0->COUNT32.SYNCBUSY.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_SWRST_1); }
262     while (ptc0->COUNT32.CTRLA.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_SYNC_SWRST_2); }
263     //CTRLA as default
264     ptc0->COUNT32.CTRLA.bit.MODE = 2; //32 bit mode
265     ptc0->COUNT32.EVCTRL.bit.TCEI = 1; //enable incoming events
266     ptc0->COUNT32.EVCTRL.bit.EVACT = 2 ; //count events
267
268     DBGC(DC_CLK_ENABLE_TIMEBASE_TC0_COMPLETE);
269
270     DBGC(DC_CLK_ENABLE_TIMEBASE_EVSYS_BEGIN);
271
272     //configure event system
273     pmclk->APBBMASK.bit.EVSYS_ = 1;
274     pgclk->PCHCTRL[EVSYS_GCLK_ID_0].bit.GEN = GEN_TC45;
275     pgclk->PCHCTRL[EVSYS_GCLK_ID_0].bit.CHEN = 1;
276     pevsys->USER[44].reg = EVSYS_ID_USER_PORT_EV_0;                               //TC0 will get event channel 0
277     pevsys->Channel[0].CHANNEL.bit.EDGSEL = EVSYS_CHANNEL_EDGSEL_RISING_EDGE_Val; //Rising edge
278     pevsys->Channel[0].CHANNEL.bit.PATH = EVSYS_CHANNEL_PATH_SYNCHRONOUS_Val;     //Synchronous
279     pevsys->Channel[0].CHANNEL.bit.EVGEN = EVSYS_ID_GEN_TC4_MCX_0;                //TC4 MC0
280
281     DBGC(DC_CLK_ENABLE_TIMEBASE_EVSYS_COMPLETE);
282
283     CLK_reset_time();
284
285     ADC0_clock_init();
286
287     DBGC(DC_CLK_ENABLE_TIMEBASE_COMPLETE);
288
289     return 0;
290 }
291
292 uint32_t CLK_get_ms(void)
293 {
294     return ms_clk;
295 }
296
297 void CLK_delay_us(uint16_t usec)
298 {
299     us_delay_done = 0;
300
301     if (TC5->COUNT16.CTRLA.bit.ENABLE)
302     {
303         TC5->COUNT16.CTRLA.bit.ENABLE = 0;
304         while (TC5->COUNT16.SYNCBUSY.bit.ENABLE) {}
305     }
306
307     if (usec < 10) usec = 0;
308     else usec -= 10;
309
310     TC5->COUNT16.CC[0].reg = usec;
311     while (TC5->COUNT16.SYNCBUSY.bit.CC0) {}
312
313     TC5->COUNT16.CTRLA.bit.ENABLE = 1;
314     while (TC5->COUNT16.SYNCBUSY.bit.ENABLE) {}
315
316     while (!us_delay_done) {}
317 }
318
319 void CLK_delay_ms(uint64_t msec)
320 {
321     msec += CLK_get_ms();
322     while (msec > CLK_get_ms()) {}
323 }
324
325 void clk_enable_sercom_apbmask(int sercomn)
326 {
327     Mclk *pmclk = MCLK;
328     switch (sercomn)
329     {
330         case 0:
331             pmclk->APBAMASK.bit.SERCOM0_ = 1;
332             break;
333         case 1:
334             pmclk->APBAMASK.bit.SERCOM1_ = 1;
335             break;
336         case 2:
337             pmclk->APBBMASK.bit.SERCOM2_ = 1;
338             break;
339         case 3:
340             pmclk->APBBMASK.bit.SERCOM3_ = 1;
341             break;
342         default:
343             break;
344     }
345 }
346
347 //call CLK_oscctrl_init first
348 //call CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT);
349 uint32_t CLK_set_spi_freq(uint8_t sercomn, uint32_t freq)
350 {
351     DBGC(DC_CLK_SET_SPI_FREQ_BEGIN);
352
353     Gclk *pgclk = GCLK;
354     Sercom *psercom = (Sercom *)sercom_apbbase[sercomn];
355     clk_enable_sercom_apbmask(sercomn);
356
357     //all gclk0 for now
358     pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.GEN = 0;
359     pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.CHEN = 1;
360
361     psercom->I2CM.CTRLA.bit.SWRST = 1;
362     while (psercom->I2CM.SYNCBUSY.bit.SWRST) {}
363     while (psercom->I2CM.CTRLA.bit.SWRST) {}
364
365     psercom->SPI.BAUD.reg = (uint8_t) (system_clks.freq_gclk[0]/2/freq-1);
366     system_clks.freq_spi = system_clks.freq_gclk[0]/2/(psercom->SPI.BAUD.reg+1);
367     system_clks.freq_sercom[sercomn] = system_clks.freq_spi;
368
369     DBGC(DC_CLK_SET_SPI_FREQ_COMPLETE);
370
371     return system_clks.freq_spi;
372 }
373
374 //call CLK_oscctrl_init first
375 //call CLK_set_i2c0_freq(CHAN_SERCOM_I2C0, FREQ_I2C0_DEFAULT);
376 uint32_t CLK_set_i2c0_freq(uint8_t sercomn, uint32_t freq)
377 {
378     DBGC(DC_CLK_SET_I2C0_FREQ_BEGIN);
379
380     Gclk *pgclk = GCLK;
381     Sercom *psercom = (Sercom *)sercom_apbbase[sercomn];
382     clk_enable_sercom_apbmask(sercomn);
383
384     //all gclk0 for now
385     pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.GEN = 0;
386     pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.CHEN = 1;
387
388     psercom->I2CM.CTRLA.bit.SWRST = 1;
389     while (psercom->I2CM.SYNCBUSY.bit.SWRST) {}
390     while (psercom->I2CM.CTRLA.bit.SWRST) {}
391
392     psercom->I2CM.BAUD.bit.BAUD = (uint8_t) (system_clks.freq_gclk[0]/2/freq-1);
393     system_clks.freq_i2c0 = system_clks.freq_gclk[0]/2/(psercom->I2CM.BAUD.bit.BAUD+1);
394     system_clks.freq_sercom[sercomn] = system_clks.freq_i2c0;
395
396     DBGC(DC_CLK_SET_I2C0_FREQ_COMPLETE);
397
398     return system_clks.freq_i2c0;
399 }
400
401 //call CLK_oscctrl_init first
402 //call CLK_set_i2c1_freq(CHAN_SERCOM_I2C1, FREQ_I2C1_DEFAULT);
403 uint32_t CLK_set_i2c1_freq(uint8_t sercomn, uint32_t freq)
404 {
405     DBGC(DC_CLK_SET_I2C1_FREQ_BEGIN);
406
407     Gclk *pgclk = GCLK;
408     Sercom *psercom = (Sercom *)sercom_apbbase[sercomn];
409     clk_enable_sercom_apbmask(sercomn);
410
411     //all gclk0 for now
412     pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.GEN = 0;
413     pgclk->PCHCTRL[sercom_pchan[sercomn]].bit.CHEN = 1;
414
415     psercom->I2CM.CTRLA.bit.SWRST = 1;
416     while (psercom->I2CM.SYNCBUSY.bit.SWRST) {}
417     while (psercom->I2CM.CTRLA.bit.SWRST) {}
418
419     psercom->I2CM.BAUD.bit.BAUD = (uint8_t) (system_clks.freq_gclk[0]/2/freq-10);
420     system_clks.freq_i2c1 = system_clks.freq_gclk[0]/2/(psercom->I2CM.BAUD.bit.BAUD+10);
421     system_clks.freq_sercom[sercomn] = system_clks.freq_i2c1;
422
423     DBGC(DC_CLK_SET_I2C1_FREQ_COMPLETE);
424
425     return system_clks.freq_i2c1;
426 }
427
428 void CLK_init(void)
429 {
430     DBGC(DC_CLK_INIT_BEGIN);
431
432     memset((void *)&system_clks,0,sizeof(system_clks));
433
434     CLK_oscctrl_init();
435     CLK_enable_timebase();
436
437     DBGC(DC_CLK_INIT_COMPLETE);
438 }
439