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 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 */ 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 */ 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 */ 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 */ 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 */ 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