1 /**
2 * \file
3 *
4 * \brief Chip-specific system clock management functions.
5 *
6 * Copyright (c) 2015 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47 #ifndef CHIP_SYSCLK_H_INCLUDED
48 #define CHIP_SYSCLK_H_INCLUDED
49
50 #include <osc.h>
51 #include <pll.h>
52
53 /**
54 * \page sysclk_quickstart Quick Start Guide for the System Clock Management
55 * service (SAMV71)
56 *
57 * This is the quick start guide for the \ref sysclk_group "System Clock
58 * Management" service, with step-by-step instructions on how to configure and
59 * use the service for specific use cases.
60 *
61 * \section sysclk_quickstart_usecases System Clock Management use cases
62 * - \ref sysclk_quickstart_basic
63 * - \ref sysclk_quickstart_use_case_2
64 *
65 * \section sysclk_quickstart_basic Basic usage of the System Clock Management
66 * service
67 * This section will present a basic use case for the System Clock Management
68 * service. This use case will configure the main system clock to 120MHz,
69 * using an internal PLL module to multiply the frequency of a crystal attached
70 * to the microcontroller.
71 *
72 * \subsection sysclk_quickstart_use_case_1_prereq Prerequisites
73 * - None
74 *
75 * \subsection sysclk_quickstart_use_case_1_setup_steps Initialization code
76 * Add to the application initialization code:
77 * \code
78 sysclk_init();
79 \endcode
80 *
81 * \subsection sysclk_quickstart_use_case_1_setup_steps_workflow Workflow
82 * -# Configure the system clocks according to the settings in conf_clock.h:
83 * \code sysclk_init(); \endcode
84 *
85 * \subsection sysclk_quickstart_use_case_1_example_code Example code
86 * Add or uncomment the following in your conf_clock.h header file,
87 * commenting out all other definitions of the same symbol(s):
88 * \code
89 #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLLACK
90
91 // Fpll0 = (Fclk * PLL_mul) / PLL_div
92 #define CONFIG_PLL0_SOURCE PLL_SRC_MAINCK_XTAL
93 #define CONFIG_PLL0_MUL (120000000UL / BOARD_FREQ_MAINCK_XTAL)
94 #define CONFIG_PLL0_DIV 1
95
96 // Fbus = Fsys / BUS_div
97 #define CONFIG_SYSCLK_PRES SYSCLK_PRES_1
98 \endcode
99 *
100 * \subsection sysclk_quickstart_use_case_1_example_workflow Workflow
101 * -# Configure the main system clock to use the output of the PLL module as
102 * its source:
103 * \code #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLLACK \endcode
104 * -# Configure the PLL module to use the fast external fast crystal
105 * oscillator as its source:
106 * \code #define CONFIG_PLL0_SOURCE PLL_SRC_MAINCK_XTAL \endcode
107 * -# Configure the PLL module to multiply the external fast crystal
108 * oscillator frequency up to 120MHz:
109 * \code
110 #define CONFIG_PLL0_MUL (120000000UL / BOARD_FREQ_MAINCK_XTAL)
111 #define CONFIG_PLL0_DIV 1
112 \endcode
113 * \note For user boards, \c BOARD_FREQ_MAINCK_XTAL should be defined in the
114 * board \c conf_board.h configuration
115 * file as the frequency of the fast crystal attached to the microcontroller.
116 * -# Configure the main clock to run at the full 120MHz, disable scaling of
117 * the main system clock speed:
118 * \code
119 #define CONFIG_SYSCLK_PRES SYSCLK_PRES_1
120 \endcode
121 * \note Some dividers are powers of two, while others are integer division
122 * factors. Refer to the formulas in the conf_clock.h template commented
123 * above each division define.
124 */
125
126 /**
127 * \page sysclk_quickstart_use_case_2 Advanced use case - Peripheral Bus Clock
128 * Management (SAMV71)
129 *
130 * \section sysclk_quickstart_use_case_2 Advanced use case - Peripheral Bus
131 * Clock Management
132 * This section will present a more advanced use case for the System Clock
133 * Management service. This use case will configure the main system clock to
134 * 96MHz, using an internal PLL module to multiply the frequency of a crystal
135 * attached to the microcontroller. The USB clock will be configured via the
136 * same PLL module.
137 *
138 * \subsection sysclk_quickstart_use_case_2_prereq Prerequisites
139 * - None
140 *
141 * \subsection sysclk_quickstart_use_case_2_setup_steps Initialization code
142 * Add to the application initialization code:
143 * \code
144 sysclk_init();
145 \endcode
146 *
147 * \subsection sysclk_quickstart_use_case_2_setup_steps_workflow Workflow
148 * -# Configure the system clocks according to the settings in conf_clock.h:
149 * \code sysclk_init(); \endcode
150 *
151 * \subsection sysclk_quickstart_use_case_2_example_code Example code
152 * Add or uncomment the following in your conf_clock.h header file,
153 * commenting out all other definitions of the same symbol(s):
154 * \code
155 #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLLACK
156
157 // Fpll0 = (Fclk * PLL_mul) / PLL_div
158 #define CONFIG_PLL0_SOURCE PLL_SRC_MAINCK_XTAL
159 #define CONFIG_PLL0_MUL (96000000UL / BOARD_FREQ_MAINCK_XTAL)
160 #define CONFIG_PLL0_DIV 1
161
162 // Fbus = Fsys / BUS_div
163 #define CONFIG_SYSCLK_PRES SYSCLK_PRES_1
164
165 // Fusb = Fsys / USB_div
166 #define CONFIG_USBCLK_SOURCE USBCLK_SRC_PLL0
167 #define CONFIG_USBCLK_DIV 2
168 \endcode
169 *
170 * \subsection sysclk_quickstart_use_case_2_example_workflow Workflow
171 * -# Configure the main system clock to use the output of the PLL0 module as
172 * its source:
173 * \code #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLLACK \endcode
174 * -# Configure the PLL0 module to use the fast external fast crystal
175 * oscillator as its source:
176 * \code #define CONFIG_PLL0_SOURCE PLL_SRC_MAINCK_XTAL \endcode
177 * -# Configure the PLL0 module to multiply the external fast crystal
178 * oscillator frequency up to 96MHz:
179 * \code
180 #define CONFIG_PLL0_MUL (96000000UL / BOARD_FREQ_MAINCK_XTAL)
181 #define CONFIG_PLL0_DIV 1
182 \endcode
183 * \note For user boards, \c BOARD_FREQ_MAINCK_XTAL should be defined in the
184 * board \c conf_board.h configuration file as the frequency of the fast
185 * crystal attached to the microcontroller.
186 * -# Configure the main clock to run at the full 96MHz, disable scaling of
187 * the main system clock speed:
188 * \code
189 #define CONFIG_SYSCLK_PRES SYSCLK_PRES_1
190 \endcode
191 * \note Some dividers are powers of two, while others are integer division
192 * factors. Refer to the formulas in the conf_clock.h template commented
193 * above each division define.
194 * -# Configure the USB module clock to use the output of the PLL0 module as
195 * its source with division 2:
196 * \code
197 #define CONFIG_USBCLK_SOURCE USBCLK_SRC_PLL0
198 #define CONFIG_USBCLK_DIV 2
199 \endcode
200 */
201
202 /// @cond 0
203 /**INDENT-OFF**/
204 #ifdef __cplusplus
205 extern "C" {
206 #endif
207 /**INDENT-ON**/
208 /// @endcond
209
210 /**
211 * \weakgroup sysclk_group
212 * @{
213 */
214
215 //! \name Configuration Symbols
216 //@{
217 /**
218 * \def CONFIG_SYSCLK_SOURCE
219 * \brief Initial/static main system clock source
220 *
221 * The main system clock will be configured to use this clock during
222 * initialization.
223 */
224 #ifndef CONFIG_SYSCLK_SOURCE
225 # define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_MAINCK_4M_RC
226 #endif
227 /**
228 * \def CONFIG_SYSCLK_PRES
229 * \brief Initial CPU clock divider (mck)
230 *
231 * The MCK will run at
232 * \f[
233 * f_{MCK} = \frac{f_{sys}}{\mathrm{CONFIG\_SYSCLK\_PRES}}\,\mbox{Hz}
234 * \f]
235 * after initialization.
236 */
237 #ifndef CONFIG_SYSCLK_PRES
238 # define CONFIG_SYSCLK_PRES 0
239 #endif
240
241 //@}
242
243 //! \name Master Clock Sources (MCK)
244 //@{
245 #define SYSCLK_SRC_SLCK_RC 0 //!< Internal 32kHz RC oscillator as master source clock
246 #define SYSCLK_SRC_SLCK_XTAL 1 //!< External 32kHz crystal oscillator as master source clock
247 #define SYSCLK_SRC_SLCK_BYPASS 2 //!< External 32kHz bypass oscillator as master source clock
248 #define SYSCLK_SRC_MAINCK_4M_RC 3 //!< Internal 4MHz RC oscillator as master source clock
249 #define SYSCLK_SRC_MAINCK_8M_RC 4 //!< Internal 8MHz RC oscillator as master source clock
250 #define SYSCLK_SRC_MAINCK_12M_RC 5 //!< Internal 12MHz RC oscillator as master source clock
251 #define SYSCLK_SRC_MAINCK_XTAL 6 //!< External crystal oscillator as master source clock
252 #define SYSCLK_SRC_MAINCK_BYPASS 7 //!< External bypass oscillator as master source clock
253 #define SYSCLK_SRC_PLLACK 8 //!< Use PLLACK as master source clock
254 #define SYSCLK_SRC_UPLLCK 9 //!< Use UPLLCK as master source clock
255 //@}
256
257 //! \name Master Clock Prescalers (MCK)
258 //@{
259 #define SYSCLK_PRES_1 PMC_MCKR_PRES_CLK_1 //!< Set master clock prescaler to 1
260 #define SYSCLK_PRES_2 PMC_MCKR_PRES_CLK_2 //!< Set master clock prescaler to 2
261 #define SYSCLK_PRES_4 PMC_MCKR_PRES_CLK_4 //!< Set master clock prescaler to 4
262 #define SYSCLK_PRES_8 PMC_MCKR_PRES_CLK_8 //!< Set master clock prescaler to 8
263 #define SYSCLK_PRES_16 PMC_MCKR_PRES_CLK_16 //!< Set master clock prescaler to 16
264 #define SYSCLK_PRES_32 PMC_MCKR_PRES_CLK_32 //!< Set master clock prescaler to 32
265 #define SYSCLK_PRES_64 PMC_MCKR_PRES_CLK_64 //!< Set master clock prescaler to 64
266 #define SYSCLK_PRES_3 PMC_MCKR_PRES_CLK_3 //!< Set master clock prescaler to 3
267 //@}
268
269 //! \name Master Clock Division (MCK)
270 //@{
271 #define SYSCLK_DIV_1 PMC_MCKR_MDIV_EQ_PCK //!< Set master clock division to 1
272 #define SYSCLK_DIV_2 PMC_MCKR_MDIV_PCK_DIV2 //!< Set master clock division to 2
273 #define SYSCLK_DIV_4 PMC_MCKR_MDIV_PCK_DIV4 //!< Set master clock division to 4
274 #define SYSCLK_DIV_3 PMC_MCKR_MDIV_PCK_DIV3 //!< Set master clock division to 3
275 //@}
276
277 //! \name USB Clock Sources
278 //@{
279 #define USBCLK_SRC_PLL0 0 //!< Use PLLA
280 #define USBCLK_SRC_UPLL 1 //!< Use UPLL
281 //@}
282
283 /**
284 * \def CONFIG_USBCLK_SOURCE
285 * \brief Configuration symbol for the USB generic clock source
286 *
287 * Sets the clock source to use for the USB. The source must also be properly
288 * configured.
289 *
290 * Define this to one of the \c USBCLK_SRC_xxx settings. Leave it undefined if
291 * USB is not required.
292 */
293 #ifdef __DOXYGEN__
294 # define CONFIG_USBCLK_SOURCE
295 #endif
296
297 /**
298 * \def CONFIG_USBCLK_DIV
299 * \brief Configuration symbol for the USB generic clock divider setting
300 *
301 * Sets the clock division for the USB generic clock. If a USB clock source is
302 * selected with CONFIG_USBCLK_SOURCE, this configuration symbol must also be
303 * defined.
304 */
305 #ifdef __DOXYGEN__
306 # define CONFIG_USBCLK_DIV
307 #endif
308
309 /**
310 * \name Querying the system clock
311 *
312 * The following functions may be used to query the current frequency of
313 * the system clock and the CPU and bus clocks derived from it.
314 * sysclk_get_main_hz() and sysclk_get_cpu_hz() can be assumed to be
315 * available on all platforms, although some platforms may define
316 * additional accessors for various chip-internal bus clocks. These are
317 * usually not intended to be queried directly by generic code.
318 */
319 //@{
320
321 /**
322 * \brief Return the current rate in Hz of the main system clock
323 *
324 * \todo This function assumes that the main clock source never changes
325 * once it's been set up, and that PLL0 always runs at the compile-time
326 * configured default rate. While this is probably the most common
327 * configuration, which we want to support as a special case for
328 * performance reasons, we will at some point need to support more
329 * dynamic setups as well.
330 */
331 #if (defined CONFIG_SYSCLK_DEFAULT_RETURNS_SLOW_OSC)
332 extern uint32_t sysclk_initialized;
333 #endif
sysclk_get_main_hz(void)334 static inline uint32_t sysclk_get_main_hz(void)
335 {
336 #if (defined CONFIG_SYSCLK_DEFAULT_RETURNS_SLOW_OSC)
337 if (!sysclk_initialized ) {
338 return OSC_MAINCK_4M_RC_HZ;
339 }
340 #endif
341
342 /* Config system clock setting */
343 if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_SLCK_RC) {
344 return OSC_SLCK_32K_RC_HZ;
345 } else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_SLCK_XTAL) {
346 return OSC_SLCK_32K_XTAL_HZ;
347 } else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_SLCK_BYPASS) {
348 return OSC_SLCK_32K_BYPASS_HZ;
349 } else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_4M_RC) {
350 return OSC_MAINCK_4M_RC_HZ;
351 } else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_8M_RC) {
352 return OSC_MAINCK_8M_RC_HZ;
353 } else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_12M_RC) {
354 return OSC_MAINCK_12M_RC_HZ;
355 } else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_XTAL) {
356 return OSC_MAINCK_XTAL_HZ;
357 } else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_BYPASS) {
358 return OSC_MAINCK_BYPASS_HZ;
359 }
360 #ifdef CONFIG_PLL0_SOURCE
361 else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_PLLACK) {
362 return pll_get_default_rate(0);
363 }
364 #endif
365
366 #ifdef CONFIG_PLL1_SOURCE
367 else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_UPLLCK) {
368 return PLL_UPLL_HZ;
369 }
370 #endif
371 else {
372 /* unhandled_case(CONFIG_SYSCLK_SOURCE); */
373 return 0;
374 }
375 }
376
377 /**
378 * \brief Return the current rate in Hz of the CPU clock
379 *
380 * \todo This function assumes that the CPU always runs at the system
381 * clock frequency. We want to support at least two more scenarios:
382 * Fixed CPU/bus clock dividers (config symbols) and dynamic CPU/bus
383 * clock dividers (which may change at run time). Ditto for all the bus
384 * clocks.
385 *
386 * \return Frequency of the CPU clock, in Hz.
387 */
sysclk_get_cpu_hz(void)388 static inline uint32_t sysclk_get_cpu_hz(void)
389 {
390 /* CONFIG_SYSCLK_PRES is the register value for setting the expected */
391 /* prescaler, not an immediate value. */
392 return sysclk_get_main_hz() /
393 ((CONFIG_SYSCLK_PRES == SYSCLK_PRES_3) ? 3 :
394 (1 << (CONFIG_SYSCLK_PRES >> PMC_MCKR_PRES_Pos)));
395 }
396
397 /**
398 * \brief Retrieves the current rate in Hz of the peripheral clocks.
399 *
400 * \return Frequency of the peripheral clocks, in Hz.
401 */
sysclk_get_peripheral_hz(void)402 static inline uint32_t sysclk_get_peripheral_hz(void)
403 {
404 /* CONFIG_SYSCLK_PRES is the register value for setting the expected */
405 /* prescaler, not an immediate value. */
406 return sysclk_get_main_hz() /
407 (((CONFIG_SYSCLK_PRES == SYSCLK_PRES_3) ? 3 : (1 << (CONFIG_SYSCLK_PRES >> PMC_MCKR_PRES_Pos))) * CONFIG_SYSCLK_DIV);
408 }
409
410 /**
411 * \brief Retrieves the current rate in Hz of the Peripheral Bus clock attached
412 * to the specified peripheral.
413 *
414 * \param module Pointer to the module's base address.
415 *
416 * \return Frequency of the bus attached to the specified peripheral, in Hz.
417 */
sysclk_get_peripheral_bus_hz(const volatile void * module)418 static inline uint32_t sysclk_get_peripheral_bus_hz(const volatile void *module)
419 {
420 UNUSED(module);
421 return sysclk_get_peripheral_hz();
422 }
423 //@}
424
425 //! \name Enabling and disabling synchronous clocks
426 //@{
427
428 /**
429 * \brief Enable a peripheral's clock.
430 *
431 * \param ul_id Id (number) of the peripheral clock.
432 */
sysclk_enable_peripheral_clock(uint32_t ul_id)433 static inline void sysclk_enable_peripheral_clock(uint32_t ul_id)
434 {
435 pmc_enable_periph_clk(ul_id);
436 }
437
438 /**
439 * \brief Disable a peripheral's clock.
440 *
441 * \param ul_id Id (number) of the peripheral clock.
442 */
sysclk_disable_peripheral_clock(uint32_t ul_id)443 static inline void sysclk_disable_peripheral_clock(uint32_t ul_id)
444 {
445 pmc_disable_periph_clk(ul_id);
446 }
447
448 //@}
449
450 //! \name System Clock Source and Prescaler configuration
451 //@{
452
453 extern void sysclk_set_prescalers(uint32_t ul_pres);
454 extern void sysclk_set_source(uint32_t ul_src);
455
456 //@}
457
458 extern void sysclk_enable_usb(void);
459 extern void sysclk_disable_usb(void);
460
461 extern void sysclk_init(void);
462
463 //! @}
464
465 /// @cond 0
466 /**INDENT-OFF**/
467 #ifdef __cplusplus
468 }
469 #endif
470 /**INDENT-ON**/
471 /// @endcond
472
473 #endif /* CHIP_SYSCLK_H_INCLUDED */
474