xref: /btstack/port/samv71-xplained-atwilc3000/ASF/common/services/clock/samv71/sysclk.h (revision 1b2596b5303dd8caeea8565532c93cca8dab8cc4)
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