/** | |
* \file | |
* | |
* \brief Chip-specific system clock management functions | |
* | |
* Copyright (c) 2012 Atmel Corporation. All rights reserved. | |
* | |
* \asf_license_start | |
* | |
* \page License | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are met: | |
* | |
* 1. Redistributions of source code must retain the above copyright notice, | |
* this list of conditions and the following disclaimer. | |
* | |
* 2. Redistributions in binary form must reproduce the above copyright notice, | |
* this list of conditions and the following disclaimer in the documentation | |
* and/or other materials provided with the distribution. | |
* | |
* 3. The name of Atmel may not be used to endorse or promote products derived | |
* from this software without specific prior written permission. | |
* | |
* 4. This software may only be redistributed and used in connection with an | |
* Atmel microcontroller product. | |
* | |
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED | |
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE | |
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR | |
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
* POSSIBILITY OF SUCH DAMAGE. | |
* | |
* \asf_license_stop | |
* | |
*/ | |
#ifndef CHIP_SYSCLK_H_INCLUDED | |
#define CHIP_SYSCLK_H_INCLUDED | |
#include <board.h> | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
/** | |
* \page sysclk_quickstart Quick Start Guide for the System Clock Management service (SAM4L) | |
* | |
* This is the quick start guide for the \ref sysclk_group "System Clock Management" | |
* service, with step-by-step instructions on how to configure and use the service for | |
* specific use cases. | |
* | |
* \section sysclk_quickstart_usecases System Clock Management use cases | |
* - \ref sysclk_quickstart_basic | |
* | |
* \section sysclk_quickstart_basic Basic usage of the System Clock Management service | |
* This section will present a basic use case for the System Clock Management service. | |
* This use case will configure the main system clock to 48MHz, using an internal DFLL | |
* module to multiply the frequency of a crystal attached to the microcontroller. The | |
* peripheral bus clocks are scaled down from the speed of the main system clock. | |
* | |
* \subsection sysclk_quickstart_use_case_1_prereq Prerequisites | |
* - None | |
* | |
* \subsection sysclk_quickstart_use_case_1_setup_steps Initialization code | |
* Add to the application initialization code: | |
* \code | |
* sysclk_init(); | |
* \endcode | |
* | |
* \subsection sysclk_quickstart_use_case_1_setup_steps_workflow Workflow | |
* -# Configure the system clocks according to the settings in conf_clock.h: | |
* \code sysclk_init(); \endcode | |
* | |
* \subsection sysclk_quickstart_use_case_1_example_code Example code | |
* Add or uncomment the following in your conf_clock.h header file, commenting out all other | |
* definitions of the same symbol(s): | |
* \code | |
* #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_DFLL0 | |
* | |
* // Fdfll = (Fclk * DFLL_mul) / DFLL_div | |
* #define CONFIG_DFLL0_SOURCE GENCLK_SRC_OSC32K | |
* #define CONFIG_DFLL0_FREQ 48000000UL | |
* #define CONFIG_DFLL0_MUL (CONFIG_DFLL0_FREQ / BOARD_OSC32_HZ) | |
* #define CONFIG_DFLL0_DIV 1 | |
* | |
* // Fbus = Fsys / (2 ^ BUS_div) | |
* #define CONFIG_SYSCLK_CPU_DIV 0 | |
* #define CONFIG_SYSCLK_PBA_DIV 1 | |
* #define CONFIG_SYSCLK_PBB_DIV 1 | |
* #define CONFIG_SYSCLK_PBC_DIV 1 | |
* #define CONFIG_SYSCLK_PBD_DIV 1 | |
* \endcode | |
* | |
* \subsection sysclk_quickstart_use_case_1_example_workflow Workflow | |
* -# Configure the main system clock to use the output of the DFLL0 module as its source: | |
* \code #define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_DFLL0 \endcode | |
* -# Configure the DFLL0 module to use external crystal oscillator OSC0 as its source: | |
* \code #define CONFIG_DFLL0_SOURCE GENCLK_SRC_OSC32K \endcode | |
* -# Configure the DFLL0 module to multiply the external oscillator OSC0 frequency up to 48MHz: | |
* \code | |
* #define CONFIG_DFLL0_FREQ 48000000UL | |
* #define CONFIG_DFLL0_MUL (CONFIG_DFLL0_FREQ / BOARD_OSC32_HZ) | |
* #define CONFIG_DFLL0_DIV 1 | |
* \endcode | |
* \note For user boards, \c BOARD_OSC0_HZ should be defined in the board \c conf_board.h configuration | |
* file as the frequency of the crystal attached to OSC0. | |
* -# Configure the main clock to run at the full 48MHz, scale the peripheral busses to run at one | |
* half (2 to the power of 1) of the system clock speed: | |
* \code | |
* #define CONFIG_SYSCLK_CPU_DIV 0 | |
* #define CONFIG_SYSCLK_PBA_DIV 1 | |
* #define CONFIG_SYSCLK_PBB_DIV 1 | |
* #define CONFIG_SYSCLK_PBC_DIV 1 | |
* #define CONFIG_SYSCLK_PBD_DIV 1 | |
* \endcode | |
* \note Some dividers are powers of two, while others are integer division factors. Refer to the | |
* formulas in the conf_clock.h template commented above each division define. | |
*/ | |
/** | |
* \weakgroup sysclk_group | |
* @{ | |
*/ | |
//! \name System clock source | |
//@{ | |
#define SYSCLK_SRC_RCSYS 0 //!< System RC oscillator | |
#define SYSCLK_SRC_OSC0 1 //!< Oscillator 0 | |
#define SYSCLK_SRC_PLL0 2 //!< Phase Locked Loop 0 | |
#define SYSCLK_SRC_DFLL 3 //!< Digital Frequency Locked Loop | |
#define SYSCLK_SRC_RC80M 4 //!< 80 MHz RC oscillator | |
#define SYSCLK_SRC_RCFAST 5 //!< 4-8-12 MHz RC oscillator | |
#define SYSCLK_SRC_RC1M 6 //!< 1 MHz RC oscillator | |
//@} | |
//! \name USB Clock Sources | |
//@{ | |
#define USBCLK_SRC_OSC0 GENCLK_SRC_OSC0 //!< Use OSC0 | |
#define USBCLK_SRC_PLL0 GENCLK_SRC_PLL0 //!< Use PLL0 | |
#define USBCLK_SRC_DFLL GENCLK_SRC_DFLL //!< Use DFLL | |
#define USBCLK_SRC_GCLKIN0 GENCLK_SRC_GCLKIN0 //!< Use GCLKIN0 | |
//@} | |
//! \name Bus index of maskable module clocks | |
//@{ | |
#define PM_CLK_GRP_CPU 0 | |
#define PM_CLK_GRP_HSB 1 | |
#define PM_CLK_GRP_PBA 2 | |
#define PM_CLK_GRP_PBB 3 | |
#define PM_CLK_GRP_PBC 4 | |
#define PM_CLK_GRP_PBD 5 | |
//@} | |
//! \name Clocks derived from the CPU clock | |
//@{ | |
//! On-Chip Debug system | |
#define SYSCLK_OCD 0 | |
//@} | |
//! \name Clocks derived from the HSB clock | |
//@{ | |
//! PDCA memory interface | |
#define SYSCLK_PDCA_HSB 0 | |
//! Flash data interface | |
#define SYSCLK_HFLASHC_DATA 1 | |
//! HRAMC data interface | |
#define SYSCLK_HRAMC1_DATA 2 | |
//! USBC DMA and FIFO interface | |
#define SYSCLK_USBC_DATA 3 | |
//! CRCCU data interface | |
#define SYSCLK_CRCCU_DATA 4 | |
//! HSB<->PBA bridge | |
#define SYSCLK_PBA_BRIDGE 5 | |
//! HSB<->PBB bridge | |
#define SYSCLK_PBB_BRIDGE 6 | |
//! HSB<->PBC bridge | |
#define SYSCLK_PBC_BRIDGE 7 | |
//! HSB<->PBD bridge | |
#define SYSCLK_PBD_BRIDGE 8 | |
//! Advanced Encryption Standard | |
#define SYSCLK_AESA_HSB 9 | |
//@} | |
//! \name Clocks derived from the PBA clock | |
//@{ | |
//! IISC Controller | |
#define SYSCLK_IISC 0 | |
//! SPI Controller | |
#define SYSCLK_SPI 1 | |
//! Timer/Counter 0 | |
#define SYSCLK_TC0 2 | |
//! Timer/Counter 1 | |
#define SYSCLK_TC1 3 | |
//! TWI Master 0 | |
#define SYSCLK_TWIM0 4 | |
//! TWI Slave 0 | |
#define SYSCLK_TWIS0 5 | |
//! TWI Master 1 | |
#define SYSCLK_TWIM1 6 | |
//! TWI Slave 1 | |
#define SYSCLK_TWIS1 7 | |
//! USART 0 | |
#define SYSCLK_USART0 8 | |
//! USART 1 | |
#define SYSCLK_USART1 9 | |
//! USART 2 | |
#define SYSCLK_USART2 10 | |
//! USART 3 | |
#define SYSCLK_USART3 11 | |
//! A/D Converter | |
#define SYSCLK_ADCIFE 12 | |
//! D/A Converter | |
#define SYSCLK_DACC 13 | |
//! Analog Comparator | |
#define SYSCLK_ACIFC 14 | |
//! Glue Logic Controller | |
#define SYSCLK_GLOC 15 | |
//! ABDACB Controller | |
#define SYSCLK_ABDACB 16 | |
//! TRNG Controller | |
#define SYSCLK_TRNG 17 | |
//! PARC Controller | |
#define SYSCLK_PARC 18 | |
//! Capacitive Touch | |
#define SYSCLK_CATB 19 | |
//! TWI Master 2 | |
#define SYSCLK_TWIM2 21 | |
//! TWI Master 3 | |
#define SYSCLK_TWIM3 22 | |
//! LCD Controller | |
#define SYSCLK_LCDCA 23 | |
//@} | |
//! \name Clocks derived from the PBB clock | |
//@{ | |
//! Flash Controller registers | |
#define SYSCLK_HFLASHC_REGS 0 | |
//! HRAMC Controller registers | |
#define SYSCLK_HRAMC1_REGS 1 | |
//! HSB Matrix configuration | |
#define SYSCLK_HMATRIX 2 | |
//! PDCA peripheral bus interface | |
#define SYSCLK_PDCA_PB 3 | |
//! CRCCU registers | |
#define SYSCLK_CRCCU_REGS 4 | |
//! USBC registers | |
#define SYSCLK_USBC_REGS 5 | |
//! PEVC Controller | |
#define SYSCLK_PEVC 6 | |
//@} | |
//! \name Clocks derived from the PBC clock | |
//@{ | |
//! PM configuration | |
#define SYSCLK_PM 0 | |
//! CHIPID Controller | |
#define SYSCLK_CHIPID 1 | |
//! System Control Interface | |
#define SYSCLK_SCIF 2 | |
//! Frequency Meter | |
#define SYSCLK_FREQM 3 | |
//! General-Purpose I/O | |
#define SYSCLK_GPIO 4 | |
//@} | |
//! \name Clocks derived from the PBD clock | |
//@{ | |
//! BPM configuration | |
#define SYSCLK_BPM 0 | |
//! BSCIF configuration | |
#define SYSCLK_BSCIF 1 | |
//! Asynchronous Timer | |
#define SYSCLK_AST 2 | |
//! Watchdog Timer | |
#define SYSCLK_WDT 3 | |
//! External Interrupt Controller | |
#define SYSCLK_EIC 4 | |
//! PICOUART | |
#define SYSCLK_PICOUART 5 | |
//@} | |
//! \name Divided clock mask derived from the PBA clock | |
//@{ | |
//! TIMER_CLOCK2 mask | |
#define PBA_DIVMASK_TIMER_CLOCK2 (1u << 0) | |
//! TIMER_CLOCK3 mask | |
#define PBA_DIVMASK_TIMER_CLOCK3 (1u << 2) | |
//! CLK_USART/DIV mask | |
#define PBA_DIVMASK_CLK_USART (1u << 2) | |
//! TIMER_CLOCK4 mask | |
#define PBA_DIVMASK_TIMER_CLOCK4 (1u << 4) | |
//! TIMER_CLOCK5 mask | |
#define PBA_DIVMASK_TIMER_CLOCK5 (1u << 6) | |
//! Bitfield mask | |
#define PBA_DIVMASK_Msk (0x7Fu << 0) | |
//@} | |
#ifndef __ASSEMBLY__ | |
#include <compiler.h> | |
#include <dfll.h> | |
#include <osc.h> | |
#include <pll.h> | |
#include <genclk.h> | |
// Use the slow clock (RCOSC) with no prescaling if config was empty. | |
#ifndef CONFIG_SYSCLK_SOURCE | |
# define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_RCSYS | |
#endif /* CONFIG_SYSCLK_SOURCE */ | |
/* | |
* Enable PicoCache for flash access by default. | |
* 0: disable PicoCache, 1: enable PicoCache. | |
*/ | |
#ifndef CONFIG_HCACHE_ENABLE | |
#define CONFIG_HCACHE_ENABLE 1 | |
#endif | |
/** | |
* \def CONFIG_SYSCLK_CPU_DIV | |
* \brief Configuration symbol for dividing the CPU clock frequency by | |
* \f$2^{CONFIG\_SYSCLK\_CPU\_DIV}\f$ | |
* | |
* If this symbol is not defined, the CPU clock frequency is not divided. | |
* | |
* This symbol may be defined in \ref conf_clock.h. | |
*/ | |
#ifndef CONFIG_SYSCLK_CPU_DIV | |
# define CONFIG_SYSCLK_CPU_DIV 0 | |
#endif /* CONFIG_SYSCLK_CPU_DIV */ | |
/** | |
* \def CONFIG_SYSCLK_INIT_HSBMASK | |
* \brief Configuration symbol for the HSB clocks enabled at power-on after the | |
* sysclock module has been initialized. By default, all HSB clocks are left | |
* enabled, however to save power these can be automatically disabled by defining | |
* this value to a mask of \c SYSCLOCK_xxx settings. | |
* | |
* If this symbol is not defined, then all HSB clocks are left enabled. | |
* | |
* This symbol may be defined in \ref conf_clock.h. | |
*/ | |
#ifdef __DOXYGEN__ | |
# define CONFIG_SYSCLK_INIT_HSBMASK | |
#endif | |
/** | |
* \def CONFIG_SYSCLK_PBA_DIV | |
* \brief Configuration symbol for dividing the PBA clock frequency by | |
* \f$2^{CONFIG\_SYSCLK\_PBA\_DIV}\f$ | |
* | |
* If this symbol is not defined, the PBA clock frequency is not divided. | |
* | |
* This symbol may be defined in \ref conf_clock.h. | |
*/ | |
#ifndef CONFIG_SYSCLK_PBA_DIV | |
# define CONFIG_SYSCLK_PBA_DIV 0 | |
#endif /* CONFIG_SYSCLK_PBA_DIV */ | |
/** | |
* \def CONFIG_SYSCLK_PBB_DIV | |
* \brief Configuration symbol for dividing the PBB clock frequency by | |
* \f$2^{CONFIG\_SYSCLK\_PBB\_DIV}\f$ | |
* | |
* If this symbol is not defined, the PBB clock frequency is not divided. | |
* | |
* This symbol may be defined in \ref conf_clock.h. | |
*/ | |
#ifndef CONFIG_SYSCLK_PBB_DIV | |
# define CONFIG_SYSCLK_PBB_DIV 0 | |
#endif /* CONFIG_SYSCLK_PBB_DIV */ | |
/** | |
* \def CONFIG_SYSCLK_PBC_DIV | |
* \brief Configuration symbol for dividing the PBC clock frequency by | |
* \f$2^{CONFIG\_SYSCLK\_PBC\_DIV}\f$ | |
* | |
* If this symbol is not defined, the PBC clock frequency is not divided. | |
* | |
* This symbol may be defined in \ref conf_clock.h. | |
*/ | |
#ifndef CONFIG_SYSCLK_PBC_DIV | |
# define CONFIG_SYSCLK_PBC_DIV 0 | |
#endif /* CONFIG_SYSCLK_PBC_DIV */ | |
/** | |
* \def CONFIG_SYSCLK_PBD_DIV | |
* \brief Configuration symbol for dividing the PBD clock frequency by | |
* \f$2^{CONFIG\_SYSCLK\_PBD\_DIV}\f$ | |
* | |
* If this symbol is not defined, the PBD clock frequency is not divided. | |
* | |
* This symbol may be defined in \ref conf_clock.h. | |
*/ | |
#ifndef CONFIG_SYSCLK_PBD_DIV | |
# define CONFIG_SYSCLK_PBD_DIV 0 | |
#endif /* CONFIG_SYSCLK_PBD_DIV */ | |
/** | |
* \def CONFIG_SYSCLK_INIT_CPUMASK | |
* \brief Configuration symbol for the CPU clocks enabled at power-on after the | |
* sysclock module has been initialized. By default, all CPU clocks are left | |
* enabled, however to save power these can be automatically disabled by defining | |
* this value to a mask of \c SYSCLOCK_xxx settings. | |
* | |
* If this symbol is not defined, then all CPU clocks are left enabled. | |
* | |
* This symbol may be defined in \ref conf_clock.h. | |
*/ | |
#ifdef __DOXYGEN__ | |
# define CONFIG_SYSCLK_INIT_CPUMASK | |
#endif | |
/** | |
* \def CONFIG_SYSCLK_INIT_PBAMASK | |
* \brief Configuration symbol for the PBA clocks enabled at power-on after the | |
* sysclock module has been initialized. By default, all PBA clocks are left | |
* enabled, however to save power these can be automatically disabled by defining | |
* this value to a mask of \c SYSCLOCK_xxx settings. | |
* | |
* If this symbol is not defined, then all PBA clocks are left enabled. | |
* | |
* This symbol may be defined in \ref conf_clock.h. | |
*/ | |
#ifdef __DOXYGEN__ | |
# define CONFIG_SYSCLK_INIT_PBAMASK | |
#endif | |
/** | |
* \def CONFIG_SYSCLK_INIT_PBBMASK | |
* \brief Configuration symbol for the PBB clocks enabled at power-on after the | |
* sysclock module has been initialized. By default, all PBB clocks are left | |
* enabled, however to save power these can be automatically disabled by defining | |
* this value to a mask of \c SYSCLOCK_xxx settings. | |
* | |
* If this symbol is not defined, then all PBB clocks are left enabled. | |
* | |
* This symbol may be defined in \ref conf_clock.h. | |
*/ | |
#ifdef __DOXYGEN__ | |
# define CONFIG_SYSCLK_INIT_PBBMASK | |
#endif | |
/** | |
* \def CONFIG_SYSCLK_INIT_PBCMASK | |
* \brief Configuration symbol for the PBC clocks enabled at power-on after the | |
* sysclock module has been initialized. By default, all PBC clocks are left | |
* enabled, however to save power these can be automatically disabled by defining | |
* this value to a mask of \c SYSCLOCK_xxx settings. | |
* | |
* If this symbol is not defined, then all PBC clocks are left enabled. | |
* | |
* This symbol may be defined in \ref conf_clock.h. | |
*/ | |
#ifdef __DOXYGEN__ | |
# define CONFIG_SYSCLK_INIT_PBCMASK | |
#endif | |
/** | |
* \def CONFIG_SYSCLK_INIT_PBDMASK | |
* \brief Configuration symbol for the PBD clocks enabled at power-on after the | |
* sysclock module has been initialized. By default, all PBD clocks are left | |
* enabled, however to save power these can be automatically disabled by defining | |
* this value to a mask of \c SYSCLOCK_xxx settings. | |
* | |
* If this symbol is not defined, then all PBD clocks are left enabled. | |
* | |
* This symbol may be defined in \ref conf_clock.h. | |
*/ | |
#ifdef __DOXYGEN__ | |
# define CONFIG_SYSCLK_INIT_PBDMASK | |
#endif | |
/** | |
* \def CONFIG_USBCLK_SOURCE | |
* \brief Configuration symbol for the USB generic clock source | |
* | |
* Sets the clock source to use for the USB. The source must also be properly | |
* configured. | |
* | |
* Define this to one of the \c USBCLK_SRC_xxx settings. Leave it undefined if | |
* USB is not required. | |
*/ | |
#ifdef __DOXYGEN__ | |
# define CONFIG_USBCLK_SOURCE | |
#endif | |
/** | |
* \def CONFIG_USBCLK_DIV | |
* \brief Configuration symbol for the USB generic clock divider setting | |
* | |
* Sets the clock division for the USB generic clock. If a USB clock source is | |
* selected with CONFIG_USBCLK_SOURCE, this configuration symbol must also be | |
* defined. | |
* | |
* Define this as any value that does not exceed \c GENCLK_DIV_MAX, and which | |
* will give a 48 MHz clock frequency from the selected source. | |
*/ | |
#ifdef __DOXYGEN__ | |
# define CONFIG_USBCLK_DIV | |
#endif | |
/** | |
* \name Querying the system clock and its derived clocks | |
* | |
* The following functions may be used to query the current frequency of | |
* the system clock and the CPU and bus clocks derived from it. | |
* sysclk_get_main_hz() and sysclk_get_cpu_hz() can be assumed to be | |
* available on all platforms, although some platforms may define | |
* additional accessors for various chip-internal bus clocks. These are | |
* usually not intended to be queried directly by generic code. | |
*/ | |
//@{ | |
/** | |
* \brief Return the current rate in Hz of the main system clock | |
* | |
* \todo This function assumes that the main clock source never changes | |
* once it's been set up, and that PLL0 always runs at the compile-time | |
* configured default rate. While this is probably the most common | |
* configuration, which we want to support as a special case for | |
* performance reasons, we will at some point need to support more | |
* dynamic setups as well. | |
*/ | |
#if (defined CONFIG_SYSCLK_DEFAULT_RETURNS_SLOW_OSC) | |
extern bool sysclk_initialized; | |
#endif | |
static inline uint32_t sysclk_get_main_hz(void) | |
{ | |
#if (defined CONFIG_SYSCLK_DEFAULT_RETURNS_SLOW_OSC) | |
if (!sysclk_initialized ) { | |
return OSC_RCSYS_NOMINAL_HZ; | |
} | |
#endif | |
if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_RCSYS) { | |
return OSC_RCSYS_NOMINAL_HZ; | |
} | |
#ifdef BOARD_OSC0_HZ | |
else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_OSC0) { | |
return BOARD_OSC0_HZ; | |
} | |
#endif | |
#ifdef CONFIG_PLL0_SOURCE | |
else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_PLL0) { | |
return pll_get_default_rate(0); | |
} | |
#endif | |
#ifdef CONFIG_DFLL0_SOURCE | |
else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_DFLL) { | |
return dfll_get_default_rate(0); | |
} | |
#endif | |
else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_RC80M) { | |
return OSC_RC80M_NOMINAL_HZ; | |
} | |
else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_RCFAST) { | |
if (CONFIG_RCFAST_FRANGE == 2) { | |
return OSC_RCFAST12M_NOMINAL_HZ; | |
} else if (CONFIG_RCFAST_FRANGE == 1) { | |
return OSC_RCFAST8M_NOMINAL_HZ; | |
} else { | |
return OSC_RCFAST4M_NOMINAL_HZ; | |
} | |
} | |
else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_RC1M) { | |
return OSC_RC1M_NOMINAL_HZ; | |
} | |
else { | |
/* unhandled_case(CONFIG_SYSCLK_SOURCE); */ | |
return 0; | |
} | |
} | |
/** | |
* \brief Return the current rate in Hz of the CPU clock | |
* | |
* \todo This function assumes that the CPU always runs at the system | |
* clock frequency. We want to support at least two more scenarios: | |
* Fixed CPU/bus clock dividers (config symbols) and dynamic CPU/bus | |
* clock dividers (which may change at run time). Ditto for all the bus | |
* clocks. | |
* | |
* \return Frequency of the CPU clock, in Hz. | |
*/ | |
static inline uint32_t sysclk_get_cpu_hz(void) | |
{ | |
return sysclk_get_main_hz() >> CONFIG_SYSCLK_CPU_DIV; | |
} | |
/** | |
* \brief Return the current rate in Hz of the High-Speed Bus clock | |
* | |
* \return Frequency of the High Speed Peripheral Bus clock, in Hz. | |
*/ | |
static inline uint32_t sysclk_get_hsb_hz(void) | |
{ | |
return sysclk_get_main_hz() >> CONFIG_SYSCLK_CPU_DIV; | |
} | |
/** | |
* \brief Return the current rate in Hz of the Peripheral Bus A clock | |
* | |
* \return Frequency of the Peripheral Bus A clock, in Hz. | |
*/ | |
static inline uint32_t sysclk_get_pba_hz(void) | |
{ | |
return sysclk_get_main_hz() >> CONFIG_SYSCLK_PBA_DIV; | |
} | |
/** | |
* \brief Return the current rate in Hz of the Peripheral Bus B clock | |
* | |
* \return Frequency of the Peripheral Bus B clock, in Hz. | |
*/ | |
static inline uint32_t sysclk_get_pbb_hz(void) | |
{ | |
return sysclk_get_main_hz() >> CONFIG_SYSCLK_PBB_DIV; | |
} | |
/** | |
* \brief Return the current rate in Hz of the Peripheral Bus C clock | |
* | |
* \return Frequency of the Peripheral Bus C clock, in Hz. | |
*/ | |
static inline uint32_t sysclk_get_pbc_hz(void) | |
{ | |
return sysclk_get_main_hz() >> CONFIG_SYSCLK_PBC_DIV; | |
} | |
/** | |
* \brief Return the current rate in Hz of the Peripheral Bus D clock | |
* | |
* \return Frequency of the Peripheral Bus D clock, in Hz. | |
*/ | |
static inline uint32_t sysclk_get_pbd_hz(void) | |
{ | |
return sysclk_get_main_hz() >> CONFIG_SYSCLK_PBD_DIV; | |
} | |
extern uint32_t sysclk_get_peripheral_bus_hz(const volatile void *module); | |
//@} | |
extern void sysclk_priv_enable_module(uint32_t bus_id, uint32_t module_index); | |
extern void sysclk_priv_disable_module(uint32_t bus_id, uint32_t module_index); | |
//! \name Enabling and disabling synchronous clocks | |
//@{ | |
/** | |
* \brief Enable a module clock derived from the CPU clock | |
* \param index Index of the module clock in the CPUMASK register | |
*/ | |
static inline void sysclk_enable_cpu_module(uint32_t index) | |
{ | |
sysclk_priv_enable_module(PM_CLK_GRP_CPU, index); | |
} | |
/** | |
* \brief Disable a module clock derived from the CPU clock | |
* \param index Index of the module clock in the CPUMASK register | |
*/ | |
static inline void sysclk_disable_cpu_module(uint32_t index) | |
{ | |
sysclk_priv_disable_module(PM_CLK_GRP_CPU, index); | |
} | |
/** | |
* \brief Enable a module clock derived from the HSB clock | |
* \param index Index of the module clock in the HSBMASK register | |
*/ | |
static inline void sysclk_enable_hsb_module(uint32_t index) | |
{ | |
sysclk_priv_enable_module(PM_CLK_GRP_HSB, index); | |
} | |
/** | |
* \brief Disable a module clock derived from the HSB clock | |
* \param index Index of the module clock in the HSBMASK register | |
*/ | |
static inline void sysclk_disable_hsb_module(uint32_t index) | |
{ | |
sysclk_priv_disable_module(PM_CLK_GRP_HSB, index); | |
} | |
extern void sysclk_enable_pba_module(uint32_t index); | |
extern void sysclk_disable_pba_module(uint32_t index); | |
extern void sysclk_enable_pbb_module(uint32_t index); | |
extern void sysclk_disable_pbb_module(uint32_t index); | |
/** | |
* \brief Enable a module clock derived from the PBC clock | |
* \param index Index of the module clock in the PBAMASK register | |
*/ | |
static inline void sysclk_enable_pbc_module(uint32_t index) | |
{ | |
sysclk_priv_enable_module(PM_CLK_GRP_PBC, index); | |
} | |
/** | |
* \brief Disable a module clock derived from the PBC clock | |
* \param index Index of the module clock in the PBAMASK register | |
*/ | |
static inline void sysclk_disable_pbc_module(uint32_t index) | |
{ | |
sysclk_priv_disable_module(PM_CLK_GRP_PBC, index); | |
} | |
/** | |
* \brief Enable a module clock derived from the PBD clock | |
* \param index Index of the module clock in the PBAMASK register | |
*/ | |
static inline void sysclk_enable_pbd_module(uint32_t index) | |
{ | |
sysclk_priv_enable_module(PM_CLK_GRP_PBD, index); | |
} | |
/** | |
* \brief Disable a module clock derived from the PBD clock | |
* \param index Index of the module clock in the PBAMASK register | |
*/ | |
static inline void sysclk_disable_pbd_module(uint32_t index) | |
{ | |
sysclk_priv_disable_module(PM_CLK_GRP_PBD, index); | |
} | |
/** | |
* \brief Enable divided clock mask derived from the PBA clock | |
* \param mask mask of the divided clock in the PBADIVMASK register | |
*/ | |
static inline void sysclk_enable_pba_divmask(uint32_t mask) | |
{ | |
uint32_t temp_mask; | |
temp_mask = PM->PM_PBADIVMASK; | |
temp_mask |= mask; | |
PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu) | |
| PM_UNLOCK_ADDR((uint32_t)&PM->PM_PBADIVMASK - (uint32_t)PM); | |
PM->PM_PBADIVMASK = temp_mask; | |
} | |
/** | |
* \brief Disable divided clock mask derived from the PBA clock | |
* \param mask mask of the divided clock in the PBADIVMASK register | |
*/ | |
static inline void sysclk_disable_pba_divmask(uint32_t mask) | |
{ | |
uint32_t temp_mask; | |
temp_mask = PM->PM_PBADIVMASK; | |
temp_mask &= ~mask; | |
PM->PM_UNLOCK = PM_UNLOCK_KEY(0xAAu) | |
| PM_UNLOCK_ADDR((uint32_t)&PM->PM_PBADIVMASK - (uint32_t)PM); | |
PM->PM_PBADIVMASK = temp_mask; | |
} | |
extern void sysclk_enable_peripheral_clock(const volatile void *module); | |
extern void sysclk_disable_peripheral_clock(const volatile void *module); | |
//@} | |
//! \name System Clock Source and Prescaler configuration | |
//@{ | |
extern void sysclk_set_prescalers(uint32_t cpu_shift, | |
uint32_t pba_shift, uint32_t pbb_shift, | |
uint32_t pbc_shift, uint32_t pbd_shift); | |
extern void sysclk_set_source(uint32_t src); | |
//@} | |
#if defined(CONFIG_USBCLK_SOURCE) || defined(__DOXYGEN__) | |
/** | |
* \def USBCLK_STARTUP_TIMEOUT | |
* \brief Number of us to wait for USB clock to start | |
*/ | |
#ifdef CONFIG_USBCLK_STARTUP_TIMEOUT | |
# define USBCLK_STARTUP_TIMEOUT (CONFIG_USBCLK_STARTUP_TIMEOUT) | |
#else | |
# define USBCLK_STARTUP_TIMEOUT (OSC0_STARTUP_TIMEOUT*(1000000/OSC_RCSYS_NOMINAL_HZ)) | |
#endif | |
extern void sysclk_enable_usb(void); | |
extern void sysclk_disable_usb(void); | |
#endif | |
extern void sysclk_init(void); | |
#endif /* !__ASSEMBLY__ */ | |
//! @} | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif /* CHIP_SYSCLK_H_INCLUDED */ |