]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/clock.c
Starting point for the SAMD20 demo.
[freertos] / FreeRTOS / Demo / CORTEX_M0+_Atmel_SAMD20_XPlained / RTOSDemo / src / ASF / sam0 / drivers / system / clock / clock.c
1 /**\r
2  * \file\r
3  *\r
4  * \brief SAM D20 Clock Driver\r
5  *\r
6  * Copyright (C) 2012-2013 Atmel Corporation. All rights reserved.\r
7  *\r
8  * \asf_license_start\r
9  *\r
10  * \page License\r
11  *\r
12  * Redistribution and use in source and binary forms, with or without\r
13  * modification, are permitted provided that the following conditions are met:\r
14  *\r
15  * 1. Redistributions of source code must retain the above copyright notice,\r
16  *    this list of conditions and the following disclaimer.\r
17  *\r
18  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
19  *    this list of conditions and the following disclaimer in the documentation\r
20  *    and/or other materials provided with the distribution.\r
21  *\r
22  * 3. The name of Atmel may not be used to endorse or promote products derived\r
23  *    from this software without specific prior written permission.\r
24  *\r
25  * 4. This software may only be redistributed and used in connection with an\r
26  *    Atmel microcontroller product.\r
27  *\r
28  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
29  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
31  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
32  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
36  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
37  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
38  * POSSIBILITY OF SUCH DAMAGE.\r
39  *\r
40  * \asf_license_stop\r
41  *\r
42  */\r
43 #include <clock.h>\r
44 #include <conf_clocks.h>\r
45 \r
46 /**\r
47  * \internal\r
48  * \brief DFLL-specific data container\r
49  */\r
50 struct _system_clock_dfll_config {\r
51         uint32_t control;\r
52         uint32_t val;\r
53         uint32_t mul;\r
54 };\r
55 \r
56 /**\r
57  * \internal\r
58  * \brief XOSC-specific data container\r
59  */\r
60 struct _system_clock_xosc_config {\r
61         uint32_t frequency;\r
62 };\r
63 \r
64 /**\r
65  * \internal\r
66  * \brief System clock module data container\r
67  */\r
68 struct _system_clock_module {\r
69         volatile struct _system_clock_dfll_config dfll;\r
70         volatile struct _system_clock_xosc_config xosc;\r
71         volatile struct _system_clock_xosc_config xosc32k;\r
72 };\r
73 \r
74 /**\r
75  * \internal\r
76  * \brief Internal module instance to cache configuration values\r
77  */\r
78 static struct _system_clock_module _system_clock_inst = {\r
79                 .dfll = {\r
80                         .control     = 0,\r
81                         .val     = 0,\r
82                         .mul     = 0,\r
83                 },\r
84                 .xosc = {\r
85                         .frequency   = 0,\r
86                 },\r
87                 .xosc32k = {\r
88                         .frequency   = 0,\r
89                 },\r
90         };\r
91 \r
92 /**\r
93  * \internal\r
94  * \brief Wait for sync to the DFLL control registers\r
95  */\r
96 static inline void _system_dfll_wait_for_sync(void)\r
97 {\r
98         while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY)) {\r
99                 /* Wait for DFLL sync */\r
100         }\r
101 }\r
102 \r
103 /**\r
104  * \internal\r
105  * \brief Wait for sync to the OSC32K control registers\r
106  */\r
107 static inline void _system_osc32k_wait_for_sync(void)\r
108 {\r
109         while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_OSC32KRDY)) {\r
110                 /* Wait for OSC32K sync */\r
111         }\r
112 }\r
113 \r
114 static inline void _system_clock_source_dfll_set_config_errata_9905(void)\r
115 {\r
116 \r
117         /* Disable ONDEMAND mode while writing configurations */\r
118         SYSCTRL->DFLLCTRL.reg = _system_clock_inst.dfll.control & ~SYSCTRL_DFLLCTRL_ONDEMAND;\r
119         _system_dfll_wait_for_sync();\r
120 \r
121         SYSCTRL->DFLLMUL.reg = _system_clock_inst.dfll.mul;\r
122         SYSCTRL->DFLLVAL.reg = _system_clock_inst.dfll.val;\r
123 \r
124         /* Write full configuration to DFLL control register */\r
125         SYSCTRL->DFLLCTRL.reg = _system_clock_inst.dfll.control;\r
126 }\r
127 \r
128 /**\r
129  * \brief Retrieve the frequency of a clock source\r
130  *\r
131  * Determines the current operating frequency of a given clock source.\r
132  *\r
133  * \param[in] clock_source  Clock source to get the frequency of\r
134  *\r
135  * \returns Frequency of the given clock source, in Hz\r
136  */\r
137 uint32_t system_clock_source_get_hz(\r
138                 const enum system_clock_source clock_source)\r
139 {\r
140         switch (clock_source) {\r
141         case SYSTEM_CLOCK_SOURCE_XOSC:\r
142                 return _system_clock_inst.xosc.frequency;\r
143 \r
144         case SYSTEM_CLOCK_SOURCE_OSC8M:\r
145                 return 8000000UL >> SYSCTRL->OSC8M.bit.PRESC;\r
146 \r
147         case SYSTEM_CLOCK_SOURCE_OSC32K:\r
148                 return 32768UL;\r
149 \r
150         case SYSTEM_CLOCK_SOURCE_ULP32K:\r
151                 return 32768UL;\r
152 \r
153         case SYSTEM_CLOCK_SOURCE_XOSC32K:\r
154                 return _system_clock_inst.xosc32k.frequency;\r
155 \r
156         case SYSTEM_CLOCK_SOURCE_DFLL:\r
157 \r
158                 /* Check if the DFLL has been configured */\r
159                 if (!(_system_clock_inst.dfll.control & SYSCTRL_DFLLCTRL_ENABLE))\r
160                         return 0;\r
161 \r
162                 /* Make sure that the DFLL module is ready */\r
163                 _system_dfll_wait_for_sync();\r
164 \r
165                 /* Check if operating in closed loop mode */\r
166                 if (_system_clock_inst.dfll.control & SYSCTRL_DFLLCTRL_MODE) {\r
167                         return system_gclk_chan_get_hz(SYSCTRL_GCLK_ID_DFLL48) *\r
168                                         (_system_clock_inst.dfll.mul & 0xffff);\r
169                 }\r
170 \r
171                 return 48000000UL;\r
172 \r
173         default:\r
174                 return 0;\r
175         }\r
176 }\r
177 \r
178 /**\r
179  * \brief Configure the internal OSC8M oscillator clock source\r
180  *\r
181  * Configures the 8MHz (nominal) internal RC oscillator with the given\r
182  * configuration settings.\r
183  *\r
184  * \param[in] config  OSC8M configuration structure containing the new config\r
185  */\r
186 void system_clock_source_osc8m_set_config(\r
187                 struct system_clock_source_osc8m_config *const config)\r
188 {\r
189         SYSCTRL_OSC8M_Type temp = SYSCTRL->OSC8M;\r
190 \r
191         /* Use temporary struct to reduce register access */\r
192         temp.bit.PRESC = config->prescaler;\r
193         temp.bit.ONDEMAND = config->on_demand;\r
194         temp.bit.RUNSTDBY = config->run_in_standby;\r
195 \r
196         SYSCTRL->OSC8M = temp;\r
197 }\r
198 \r
199 /**\r
200  * \brief Configure the internal OSC32K oscillator clock source\r
201  *\r
202  * Configures the 32KHz (nominal) internal RC oscillator with the given\r
203  * configuration settings.\r
204  *\r
205  * \param[in] config  OSC32K configuration structure containing the new config\r
206  */\r
207 void system_clock_source_osc32k_set_config(\r
208                 struct system_clock_source_osc32k_config *const config)\r
209 {\r
210         SYSCTRL_OSC32K_Type temp = SYSCTRL->OSC32K;\r
211 \r
212         /* Update settings via a temporary struct to reduce register access */\r
213         temp.bit.EN1K     = config->enable_1khz_output;\r
214         temp.bit.EN32K    = config->enable_32khz_output;\r
215         temp.bit.STARTUP  = config->startup_time;\r
216         temp.bit.ONDEMAND = config->on_demand;\r
217         temp.bit.RUNSTDBY = config->run_in_standby;\r
218 \r
219         SYSCTRL->OSC32K  = temp;\r
220 }\r
221 \r
222 /**\r
223  * \brief Configure the external oscillator clock source\r
224  *\r
225  * Configures the external oscillator clock source with the given configuration\r
226  * settings.\r
227  *\r
228  * \param[in] config  External oscillator configuration structure containing\r
229  *                    the new config\r
230  */\r
231 void system_clock_source_xosc_set_config(\r
232                 struct system_clock_source_xosc_config *const config)\r
233 {\r
234         SYSCTRL_XOSC_Type temp = SYSCTRL->XOSC;\r
235 \r
236         temp.bit.STARTUP = config->startup_time;\r
237 \r
238         if (config->external_clock == SYSTEM_CLOCK_EXTERNAL_CRYSTAL) {\r
239                 temp.bit.XTALEN = 1;\r
240         } else {\r
241                 temp.bit.XTALEN = 0;\r
242         }\r
243 \r
244         temp.bit.AMPGC = config->auto_gain_control;\r
245 \r
246         /* Set gain if automatic gain control is not selected */\r
247         if (!config->auto_gain_control) {\r
248                 if (config->frequency <= 2000000) {\r
249                         temp.bit.GAIN = 0;\r
250                 } else if (config->frequency <= 4000000) {\r
251                         temp.bit.GAIN = 1;\r
252                 } else if (config->frequency <= 8000000) {\r
253                         temp.bit.GAIN = 2;\r
254                 } else if (config->frequency <= 16000000) {\r
255                         temp.bit.GAIN = 3;\r
256                 } else if (config->frequency <= 30000000) {\r
257                         temp.bit.GAIN = 4;\r
258                 }\r
259 \r
260         }\r
261 \r
262         temp.bit.ONDEMAND = config->on_demand;\r
263         temp.bit.RUNSTDBY = config->run_in_standby;\r
264 \r
265         /* Store XOSC frequency for internal use */\r
266         _system_clock_inst.xosc.frequency = config->frequency;\r
267 \r
268         SYSCTRL->XOSC = temp;\r
269 }\r
270 \r
271 /**\r
272  * \brief Configure the XOSC32K external 32KHz oscillator clock source\r
273  *\r
274  * Configures the external 32KHz oscillator clock source with the given\r
275  * configuration settings.\r
276  *\r
277  * \param[in] config  XOSC32K configuration structure containing the new config\r
278  */\r
279 void system_clock_source_xosc32k_set_config(\r
280                 struct system_clock_source_xosc32k_config *const config)\r
281 {\r
282         SYSCTRL_XOSC32K_Type temp = SYSCTRL->XOSC32K;\r
283 \r
284         temp.bit.STARTUP = config->startup_time;\r
285 \r
286         if (config->external_clock == SYSTEM_CLOCK_EXTERNAL_CRYSTAL) {\r
287                 temp.bit.XTALEN = 1;\r
288         } else {\r
289                 temp.bit.XTALEN = 0;\r
290         }\r
291 \r
292         temp.bit.AAMPEN = config->auto_gain_control;\r
293         temp.bit.EN1K = config->enable_1khz_output;\r
294         temp.bit.EN32K = config->enable_32khz_output;\r
295 \r
296         temp.bit.ONDEMAND = config->on_demand;\r
297         temp.bit.RUNSTDBY = config->run_in_standby;\r
298 \r
299         /* Cache the new frequency in case the user needs to check the current\r
300          * operating frequency later */\r
301         _system_clock_inst.xosc32k.frequency = config->frequency;\r
302 \r
303         SYSCTRL->XOSC32K = temp;\r
304 }\r
305 \r
306 /**\r
307  * \brief Configure the DFLL clock source\r
308  *\r
309  * Configures the Digital Frequency Locked Loop clock source with the given\r
310  * configuration settings.\r
311  *\r
312  * \note The DFLL will be running when this function returns, as the DFLL module\r
313  *       needs to be enabled in order to perform the module configuration.\r
314  *\r
315  * \param[in] config  DFLL configuration structure containing the new config\r
316  */\r
317 void system_clock_source_dfll_set_config(\r
318                 struct system_clock_source_dfll_config *const config)\r
319 {\r
320         _system_clock_inst.dfll.val =\r
321                         SYSCTRL_DFLLVAL_COARSE(config->coarse_value) |\r
322                         SYSCTRL_DFLLVAL_FINE(config->fine_value);\r
323 \r
324         _system_clock_inst.dfll.control =\r
325                         (uint32_t)config->wakeup_lock     |\r
326                         (uint32_t)config->stable_tracking |\r
327                         (uint32_t)config->quick_lock      |\r
328                         (uint32_t)config->chill_cycle     |\r
329                         (uint32_t)config->run_in_standby << SYSCTRL_DFLLCTRL_RUNSTDBY_Pos |\r
330                         (uint32_t)config->on_demand << SYSCTRL_DFLLCTRL_ONDEMAND_Pos;\r
331 \r
332         if (config->loop_mode == SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED) {\r
333                 _system_clock_inst.dfll.mul =\r
334                                 SYSCTRL_DFLLMUL_CSTEP(config->coarse_max_step) |\r
335                                 SYSCTRL_DFLLMUL_FSTEP(config->fine_max_step)   |\r
336                                 SYSCTRL_DFLLMUL_MUL(config->multiply_factor);\r
337 \r
338                 /* Enable the closed loop mode */\r
339                 _system_clock_inst.dfll.control |= config->loop_mode;\r
340         }\r
341 }\r
342 \r
343 /**\r
344  * \brief Writes the calibration values for a given oscillator clock source\r
345  *\r
346  * Writes an oscillator calibration value to the given oscillator control\r
347  * registers. The acceptable ranges are:\r
348  *\r
349  * For OSC32K:\r
350  *  - 7 bits (max value 128)\r
351  * For OSC8MHZ:\r
352  *  - 8 bits (Max value 255)\r
353  * For OSCULP:\r
354  *  - 5 bits (Max value 32)\r
355  *\r
356  * \note The frequency range parameter applies only when configuring the 8MHz\r
357  *       oscillator and will be ignored for the other oscillators.\r
358  *\r
359  * \param[in] clock_source       Clock source to calibrate\r
360  * \param[in] calibration_value  Calibration value to write\r
361  * \param[in] freq_range         Frequency range (8MHz oscillator only)\r
362  *\r
363  * \retval STATUS_ERR_INVALID_ARG  The selected clock source is not available\r
364  */\r
365 enum status_code system_clock_source_write_calibration(\r
366                 const enum system_clock_source clock_source,\r
367                 const uint16_t calibration_value,\r
368                 const uint8_t freq_range)\r
369 {\r
370         switch (clock_source) {\r
371         case SYSTEM_CLOCK_SOURCE_OSC8M:\r
372 \r
373                 if (calibration_value > 0xfff || freq_range > 4) {\r
374                         return STATUS_ERR_INVALID_ARG;\r
375                 }\r
376 \r
377                 SYSCTRL->OSC8M.bit.CALIB  = calibration_value;\r
378                 SYSCTRL->OSC8M.bit.FRANGE = freq_range;\r
379                 break;\r
380 \r
381         case SYSTEM_CLOCK_SOURCE_OSC32K:\r
382 \r
383                 if (calibration_value > 128) {\r
384                         return STATUS_ERR_INVALID_ARG;\r
385                 }\r
386 \r
387                 _system_osc32k_wait_for_sync();\r
388                 SYSCTRL->OSC32K.bit.CALIB = calibration_value;\r
389                 break;\r
390 \r
391         case SYSTEM_CLOCK_SOURCE_ULP32K:\r
392 \r
393                 if (calibration_value > 32) {\r
394                         return STATUS_ERR_INVALID_ARG;\r
395                 }\r
396 \r
397                 SYSCTRL->OSCULP32K.bit.CALIB = calibration_value;\r
398                 break;\r
399 \r
400         default:\r
401                 Assert(false);\r
402                 return STATUS_ERR_INVALID_ARG;\r
403                 break;\r
404         }\r
405 \r
406         return STATUS_OK;\r
407 }\r
408 \r
409 /**\r
410  * \brief Enables a clock source\r
411  *\r
412  * Enables a clock source which has been previously configured.\r
413  *\r
414  * \param[in] clock_source       Clock source to enable\r
415  *\r
416  * \retval STATUS_OK               Clock source was enabled successfully and\r
417  *                                 is ready\r
418  * \retval STATUS_ERR_INVALID_ARG  The clock source is not available on this\r
419  *                                 device\r
420  *\r
421  * \retval STATUS_ERR_NOT_INITIALIZED DFLL configuration is not initialized\r
422  */\r
423 enum status_code system_clock_source_enable(\r
424                 const enum system_clock_source clock_source)\r
425 {\r
426         switch (clock_source) {\r
427         case SYSTEM_CLOCK_SOURCE_OSC8M:\r
428                 SYSCTRL->OSC8M.reg |= SYSCTRL_OSC8M_ENABLE;\r
429                 return STATUS_OK;\r
430 \r
431         case SYSTEM_CLOCK_SOURCE_OSC32K:\r
432                 SYSCTRL->OSC32K.reg |= SYSCTRL_OSC32K_ENABLE;\r
433                 break;\r
434 \r
435         case SYSTEM_CLOCK_SOURCE_XOSC:\r
436                 SYSCTRL->XOSC.reg |= SYSCTRL_XOSC_ENABLE;\r
437                 break;\r
438 \r
439         case SYSTEM_CLOCK_SOURCE_XOSC32K:\r
440                 SYSCTRL->XOSC32K.reg |= SYSCTRL_XOSC32K_ENABLE;\r
441                 break;\r
442 \r
443         case SYSTEM_CLOCK_SOURCE_DFLL:\r
444                 _system_clock_inst.dfll.control |= SYSCTRL_DFLLCTRL_ENABLE;\r
445                 _system_clock_source_dfll_set_config_errata_9905();\r
446                 break;\r
447 \r
448         case SYSTEM_CLOCK_SOURCE_ULP32K:\r
449                 /* Always enabled */\r
450                 return STATUS_OK;\r
451 \r
452         default:\r
453                 Assert(false);\r
454                 return STATUS_ERR_INVALID_ARG;\r
455         }\r
456 \r
457         return STATUS_OK;\r
458 }\r
459 \r
460 /**\r
461  * \brief Disables a clock source\r
462  *\r
463  * Disables a clock source that was previously enabled.\r
464  *\r
465  * \param[in] clock_source  Clock source to disable\r
466  *\r
467  * \retval STATUS_OK               Clock source was disabled successfully\r
468  * \retval STATUS_ERR_INVALID_ARG  An invalid or unavailable clock source was\r
469  *                                 given\r
470  */\r
471 enum status_code system_clock_source_disable(\r
472                 const enum system_clock_source clock_source)\r
473 {\r
474         switch (clock_source) {\r
475         case SYSTEM_CLOCK_SOURCE_OSC8M:\r
476                 SYSCTRL->OSC8M.reg &= ~SYSCTRL_OSC8M_ENABLE;\r
477                 break;\r
478 \r
479         case SYSTEM_CLOCK_SOURCE_OSC32K:\r
480                 SYSCTRL->OSC32K.reg &= ~SYSCTRL_OSC32K_ENABLE;\r
481                 break;\r
482 \r
483         case SYSTEM_CLOCK_SOURCE_XOSC:\r
484                 SYSCTRL->XOSC.reg &= ~SYSCTRL_XOSC_ENABLE;\r
485                 break;\r
486 \r
487         case SYSTEM_CLOCK_SOURCE_XOSC32K:\r
488                 SYSCTRL->XOSC32K.reg &= ~SYSCTRL_XOSC32K_ENABLE;\r
489                 break;\r
490 \r
491         case SYSTEM_CLOCK_SOURCE_DFLL:\r
492                 _system_clock_inst.dfll.control &= ~SYSCTRL_DFLLCTRL_ENABLE;\r
493                 SYSCTRL->DFLLCTRL.reg = _system_clock_inst.dfll.control;\r
494                 break;\r
495 \r
496         case SYSTEM_CLOCK_SOURCE_ULP32K:\r
497                 /* Not possible to disable */\r
498                 return STATUS_ERR_INVALID_ARG;\r
499 \r
500         default:\r
501                 return STATUS_ERR_INVALID_ARG;\r
502         }\r
503 \r
504         return STATUS_OK;\r
505 }\r
506 \r
507 /**\r
508  * \brief Checks if a clock source is ready\r
509  *\r
510  * Checks if a given clock source is ready to be used.\r
511  *\r
512  * \param[in] clock_source  Clock source to check if ready\r
513  *\r
514  * \returns Ready state of the given clock source.\r
515  *\r
516  * \retval true   Clock source is enabled and ready\r
517  * \retval false  Clock source is disabled or not yet ready\r
518  */\r
519 bool system_clock_source_is_ready(\r
520                 const enum system_clock_source clock_source)\r
521 {\r
522         uint32_t mask;\r
523 \r
524         switch (clock_source) {\r
525         case SYSTEM_CLOCK_SOURCE_OSC8M:\r
526                 mask = SYSCTRL_PCLKSR_OSC8MRDY;\r
527                 break;\r
528 \r
529         case SYSTEM_CLOCK_SOURCE_OSC32K:\r
530                 mask = SYSCTRL_PCLKSR_OSC32KRDY;\r
531                 break;\r
532 \r
533         case SYSTEM_CLOCK_SOURCE_XOSC:\r
534                 mask = SYSCTRL_PCLKSR_XOSCRDY;\r
535                 break;\r
536 \r
537         case SYSTEM_CLOCK_SOURCE_XOSC32K:\r
538                 mask = SYSCTRL_PCLKSR_XOSC32KRDY;\r
539                 break;\r
540 \r
541         case SYSTEM_CLOCK_SOURCE_DFLL:\r
542                 mask = SYSCTRL_PCLKSR_DFLLRDY;\r
543                 break;\r
544 \r
545         case SYSTEM_CLOCK_SOURCE_ULP32K:\r
546                 /* Not possible to disable */\r
547                 return true;\r
548 \r
549         default:\r
550                 return false;\r
551         }\r
552 \r
553         return ((SYSCTRL->PCLKSR.reg & mask) != 0);\r
554 }\r
555 \r
556 /* Include some checks for conf_clocks.h validation */\r
557 #include "clock_config_check.h"\r
558 \r
559 #if !defined(__DOXYGEN__)\r
560 /** \internal\r
561  *\r
562  * Configures a Generic Clock Generator with the configuration from \c conf_clocks.h.\r
563  */\r
564 #  define _CONF_CLOCK_GCLK_CONFIG(n, unused) \\r
565         if (CONF_CLOCK_GCLK_##n##_ENABLE == true) { \\r
566                 struct system_gclk_gen_config gclk_conf;                          \\r
567                 system_gclk_gen_get_config_defaults(&gclk_conf);                  \\r
568                 gclk_conf.source_clock    = CONF_CLOCK_GCLK_##n##_CLOCK_SOURCE;   \\r
569                 gclk_conf.division_factor = CONF_CLOCK_GCLK_##n##_PRESCALER;      \\r
570                 gclk_conf.run_in_standby  = CONF_CLOCK_GCLK_##n##_RUN_IN_STANDBY; \\r
571                 gclk_conf.output_enable   = CONF_CLOCK_GCLK_##n##_OUTPUT_ENABLE;  \\r
572                 system_gclk_gen_set_config(GCLK_GENERATOR_##n, &gclk_conf);       \\r
573                 system_gclk_gen_enable(GCLK_GENERATOR_##n);                       \\r
574         }\r
575 \r
576 /** \internal\r
577  *\r
578  * Configures a Generic Clock Generator with the configuration from \c conf_clocks.h,\r
579  * provided that it is not the main Generic Clock Generator channel.\r
580  */\r
581 #  define _CONF_CLOCK_GCLK_CONFIG_NONMAIN(n, unused) \\r
582                 if (n > 0) { _CONF_CLOCK_GCLK_CONFIG(n, unused); }\r
583 #endif\r
584 \r
585 /**\r
586  * \brief Initialize clock system based on the configuration in conf_clocks.h\r
587  *\r
588  * This function will apply the settings in conf_clocks.h when run from the user\r
589  * application. All clock sources and GCLK generators are running when this function\r
590  * returns.\r
591  */\r
592 void system_clock_init(void)\r
593 {\r
594         /* Workaround for errata 10558 */\r
595         SYSCTRL->INTFLAG.reg = SYSCTRL_INTFLAG_BOD12RDY | SYSCTRL_INTFLAG_BOD33RDY |\r
596                         SYSCTRL_INTFLAG_BOD12DET | SYSCTRL_INTFLAG_BOD33DET |\r
597                         SYSCTRL_INTFLAG_DFLLRDY;\r
598 \r
599         system_flash_set_waitstates(CONF_CLOCK_FLASH_WAIT_STATES);\r
600 \r
601         /* XOSC */\r
602 #if CONF_CLOCK_XOSC_ENABLE == true\r
603         struct system_clock_source_xosc_config xosc_conf;\r
604         system_clock_source_xosc_get_config_defaults(&xosc_conf);\r
605 \r
606         xosc_conf.external_clock    = CONF_CLOCK_XOSC_EXTERNAL_CRYSTAL;\r
607         xosc_conf.startup_time      = CONF_CLOCK_XOSC_STARTUP_TIME;\r
608         xosc_conf.auto_gain_control = CONF_CLOCK_XOSC_AUTO_GAIN_CONTROL;\r
609         xosc_conf.frequency         = CONF_CLOCK_XOSC_EXTERNAL_FREQUENCY;\r
610         xosc_conf.on_demand         = CONF_CLOCK_XOSC_ON_DEMAND;\r
611         xosc_conf.run_in_standby    = CONF_CLOCK_XOSC_RUN_IN_STANDBY;\r
612 \r
613         system_clock_source_xosc_set_config(&xosc_conf);\r
614         system_clock_source_enable(SYSTEM_CLOCK_SOURCE_XOSC);\r
615 #endif\r
616 \r
617 \r
618         /* XOSC32K */\r
619 #if CONF_CLOCK_XOSC32K_ENABLE == true\r
620         struct system_clock_source_xosc32k_config xosc32k_conf;\r
621         system_clock_source_xosc32k_get_config_defaults(&xosc32k_conf);\r
622 \r
623         xosc32k_conf.frequency           = 32768UL;\r
624         xosc32k_conf.external_clock      = CONF_CLOCK_XOSC32K_EXTERNAL_CRYSTAL;\r
625         xosc32k_conf.startup_time        = CONF_CLOCK_XOSC32K_STARTUP_TIME;\r
626         xosc32k_conf.auto_gain_control   = CONF_CLOCK_XOSC32K_AUTO_AMPLITUDE_CONTROL;\r
627         xosc32k_conf.enable_1khz_output  = CONF_CLOCK_XOSC32K_ENABLE_1KHZ_OUPUT;\r
628         xosc32k_conf.enable_32khz_output = CONF_CLOCK_XOSC32K_ENABLE_32KHZ_OUTPUT;\r
629         xosc32k_conf.on_demand           = CONF_CLOCK_XOSC32K_ON_DEMAND;\r
630         xosc32k_conf.run_in_standby      = CONF_CLOCK_XOSC32K_RUN_IN_STANDBY;\r
631 \r
632         system_clock_source_xosc32k_set_config(&xosc32k_conf);\r
633         system_clock_source_enable(SYSTEM_CLOCK_SOURCE_XOSC32K);\r
634 #endif\r
635 \r
636 \r
637         /* OSCK32K */\r
638 #if CONF_CLOCK_OSC32K_ENABLE == true\r
639         SYSCTRL->OSC32K.bit.CALIB =\r
640                         (*(uint32_t *)SYSCTRL_FUSES_OSC32KCAL_ADDR >> SYSCTRL_FUSES_OSC32KCAL_Pos);\r
641 \r
642         struct system_clock_source_osc32k_config osc32k_conf;\r
643         system_clock_source_osc32k_get_config_defaults(&osc32k_conf);\r
644 \r
645         osc32k_conf.startup_time        = CONF_CLOCK_OSC32K_STARTUP_TIME;\r
646         osc32k_conf.enable_1khz_output  = CONF_CLOCK_OSC32K_ENABLE_1KHZ_OUTPUT;\r
647         osc32k_conf.enable_32khz_output = CONF_CLOCK_OSC32K_ENABLE_32KHZ_OUTPUT;\r
648         osc32k_conf.on_demand           = CONF_CLOCK_OSC32K_ON_DEMAND;\r
649         osc32k_conf.run_in_standby      = CONF_CLOCK_OSC32K_RUN_IN_STANDBY;\r
650 \r
651         system_clock_source_osc32k_set_config(&osc32k_conf);\r
652         system_clock_source_enable(SYSTEM_CLOCK_SOURCE_OSC32K);\r
653 #endif\r
654 \r
655 \r
656         /* DFLL (Open and Closed Loop) */\r
657 #if CONF_CLOCK_DFLL_ENABLE == true\r
658         struct system_clock_source_dfll_config dfll_conf;\r
659         system_clock_source_dfll_get_config_defaults(&dfll_conf);\r
660 \r
661         dfll_conf.loop_mode      = CONF_CLOCK_DFLL_LOOP_MODE;\r
662         dfll_conf.on_demand      = CONF_CLOCK_DFLL_ON_DEMAND;\r
663         dfll_conf.run_in_standby = CONF_CLOCK_DFLL_RUN_IN_STANDBY;\r
664 \r
665         if (CONF_CLOCK_DFLL_LOOP_MODE == SYSTEM_CLOCK_DFLL_LOOP_MODE_OPEN) {\r
666                 dfll_conf.coarse_value = CONF_CLOCK_DFLL_COARSE_VALUE;\r
667                 dfll_conf.fine_value   = CONF_CLOCK_DFLL_FINE_VALUE;\r
668         }\r
669 \r
670 #  if CONF_CLOCK_DFLL_QUICK_LOCK == true\r
671         dfll_conf.quick_lock = SYSTEM_CLOCK_DFLL_QUICK_LOCK_ENABLE;\r
672 #  else\r
673         dfll_conf.quick_lock = SYSTEM_CLOCK_DFLL_QUICK_LOCK_DISABLE;\r
674 #  endif\r
675 \r
676 #  if CONF_CLOCK_DFLL_TRACK_AFTER_FINE_LOCK == true\r
677         dfll_conf.stable_tracking = SYSTEM_CLOCK_DFLL_STABLE_TRACKING_TRACK_AFTER_LOCK;\r
678 #  else\r
679         dfll_conf.stable_tracking = SYSTEM_CLOCK_DFLL_STABLE_TRACKING_FIX_AFTER_LOCK;\r
680 #  endif\r
681 \r
682 #  if CONF_CLOCK_DFLL_KEEP_LOCK_ON_WAKEUP == true\r
683         dfll_conf.wakeup_lock = SYSTEM_CLOCK_DFLL_WAKEUP_LOCK_KEEP;\r
684 #  else\r
685         dfll_conf.wakeup_lock = SYSTEM_CLOCK_DFLL_WAKEUP_LOCK_LOSE;\r
686 #  endif\r
687 \r
688 #  if CONF_CLOCK_DFLL_ENABLE_CHILL_CYCLE == true\r
689         dfll_conf.chill_cycle = SYSTEM_CLOCK_DFLL_CHILL_CYCLE_ENABLE;\r
690 #  else\r
691         dfll_conf.chill_cycle = SYSTEM_CLOCK_DFLL_CHILL_CYCLE_DISABLE;\r
692 #  endif\r
693 \r
694         if (CONF_CLOCK_DFLL_LOOP_MODE == SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED) {\r
695                 dfll_conf.multiply_factor = CONF_CLOCK_DFLL_MULTIPLY_FACTOR;\r
696         }\r
697 \r
698         dfll_conf.coarse_max_step = CONF_CLOCK_DFLL_MAX_COARSE_STEP_SIZE;\r
699         dfll_conf.fine_max_step   = CONF_CLOCK_DFLL_MAX_FINE_STEP_SIZE;\r
700 \r
701         system_clock_source_dfll_set_config(&dfll_conf);\r
702         system_clock_source_enable(SYSTEM_CLOCK_SOURCE_DFLL);\r
703 #endif\r
704 \r
705 \r
706         /* OSC8M */\r
707         struct system_clock_source_osc8m_config osc8m_conf;\r
708         system_clock_source_osc8m_get_config_defaults(&osc8m_conf);\r
709 \r
710         osc8m_conf.prescaler      = CONF_CLOCK_OSC8M_PRESCALER;\r
711         osc8m_conf.on_demand      = CONF_CLOCK_OSC8M_ON_DEMAND;\r
712         osc8m_conf.run_in_standby = CONF_CLOCK_OSC8M_RUN_IN_STANDBY;\r
713 \r
714         system_clock_source_osc8m_set_config(&osc8m_conf);\r
715         system_clock_source_enable(SYSTEM_CLOCK_SOURCE_OSC8M);\r
716 \r
717 \r
718         /* GCLK */\r
719 #if CONF_CLOCK_CONFIGURE_GCLK == true\r
720         system_gclk_init();\r
721 \r
722         /* Configure all GCLK generators except for the main generator, which\r
723          * is configured later after all other clock systems are set up */\r
724         MREPEAT(GCLK_GEN_NUM_MSB, _CONF_CLOCK_GCLK_CONFIG_NONMAIN, ~);\r
725 \r
726 #  if (CONF_CLOCK_DFLL_ENABLE)\r
727         /* Enable DFLL reference clock if in closed loop mode */\r
728         if (CONF_CLOCK_DFLL_LOOP_MODE == SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED) {\r
729                 struct system_gclk_chan_config dfll_gclk_chan_conf;\r
730 \r
731                 system_gclk_chan_get_config_defaults(&dfll_gclk_chan_conf);\r
732                 dfll_gclk_chan_conf.source_generator = CONF_CLOCK_DFLL_SOURCE_GCLK_GENERATOR;\r
733                 system_gclk_chan_set_config(SYSCTRL_GCLK_ID_DFLL48, &dfll_gclk_chan_conf);\r
734                 system_gclk_chan_enable(SYSCTRL_GCLK_ID_DFLL48);\r
735         }\r
736 #  endif\r
737 \r
738         /* Configure the main GCLK last as it might depend on other generators */\r
739         _CONF_CLOCK_GCLK_CONFIG(0, ~);\r
740 #endif\r
741 \r
742 \r
743         /* CPU and BUS clocks */\r
744         system_cpu_clock_set_divider(CONF_CLOCK_CPU_DIVIDER);\r
745         system_main_clock_set_failure_detect(CONF_CLOCK_CPU_CLOCK_FAILURE_DETECT);\r
746         system_apb_clock_set_divider(SYSTEM_CLOCK_APB_APBA, CONF_CLOCK_APBA_DIVIDER);\r
747         system_apb_clock_set_divider(SYSTEM_CLOCK_APB_APBB, CONF_CLOCK_APBB_DIVIDER);\r
748 }\r