1*1b2596b5SMatthias Ringwald /**
2*1b2596b5SMatthias Ringwald * \file
3*1b2596b5SMatthias Ringwald *
4*1b2596b5SMatthias Ringwald * \brief Chip-specific system clock management functions.
5*1b2596b5SMatthias Ringwald *
6*1b2596b5SMatthias Ringwald * Copyright (c) 2015 Atmel Corporation. All rights reserved.
7*1b2596b5SMatthias Ringwald *
8*1b2596b5SMatthias Ringwald * \asf_license_start
9*1b2596b5SMatthias Ringwald *
10*1b2596b5SMatthias Ringwald * \page License
11*1b2596b5SMatthias Ringwald *
12*1b2596b5SMatthias Ringwald * Redistribution and use in source and binary forms, with or without
13*1b2596b5SMatthias Ringwald * modification, are permitted provided that the following conditions are met:
14*1b2596b5SMatthias Ringwald *
15*1b2596b5SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright notice,
16*1b2596b5SMatthias Ringwald * this list of conditions and the following disclaimer.
17*1b2596b5SMatthias Ringwald *
18*1b2596b5SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright notice,
19*1b2596b5SMatthias Ringwald * this list of conditions and the following disclaimer in the documentation
20*1b2596b5SMatthias Ringwald * and/or other materials provided with the distribution.
21*1b2596b5SMatthias Ringwald *
22*1b2596b5SMatthias Ringwald * 3. The name of Atmel may not be used to endorse or promote products derived
23*1b2596b5SMatthias Ringwald * from this software without specific prior written permission.
24*1b2596b5SMatthias Ringwald *
25*1b2596b5SMatthias Ringwald * 4. This software may only be redistributed and used in connection with an
26*1b2596b5SMatthias Ringwald * Atmel microcontroller product.
27*1b2596b5SMatthias Ringwald *
28*1b2596b5SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29*1b2596b5SMatthias Ringwald * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30*1b2596b5SMatthias Ringwald * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31*1b2596b5SMatthias Ringwald * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32*1b2596b5SMatthias Ringwald * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33*1b2596b5SMatthias Ringwald * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34*1b2596b5SMatthias Ringwald * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35*1b2596b5SMatthias Ringwald * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36*1b2596b5SMatthias Ringwald * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37*1b2596b5SMatthias Ringwald * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38*1b2596b5SMatthias Ringwald * POSSIBILITY OF SUCH DAMAGE.
39*1b2596b5SMatthias Ringwald *
40*1b2596b5SMatthias Ringwald * \asf_license_stop
41*1b2596b5SMatthias Ringwald *
42*1b2596b5SMatthias Ringwald */
43*1b2596b5SMatthias Ringwald /*
44*1b2596b5SMatthias Ringwald * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45*1b2596b5SMatthias Ringwald */
46*1b2596b5SMatthias Ringwald
47*1b2596b5SMatthias Ringwald #include <sysclk.h>
48*1b2596b5SMatthias Ringwald
49*1b2596b5SMatthias Ringwald /// @cond 0
50*1b2596b5SMatthias Ringwald /**INDENT-OFF**/
51*1b2596b5SMatthias Ringwald #ifdef __cplusplus
52*1b2596b5SMatthias Ringwald extern "C" {
53*1b2596b5SMatthias Ringwald #endif
54*1b2596b5SMatthias Ringwald /**INDENT-ON**/
55*1b2596b5SMatthias Ringwald /// @endcond
56*1b2596b5SMatthias Ringwald
57*1b2596b5SMatthias Ringwald /**
58*1b2596b5SMatthias Ringwald * \weakgroup sysclk_group
59*1b2596b5SMatthias Ringwald * @{
60*1b2596b5SMatthias Ringwald */
61*1b2596b5SMatthias Ringwald
62*1b2596b5SMatthias Ringwald #if defined(CONFIG_SYSCLK_DEFAULT_RETURNS_SLOW_OSC)
63*1b2596b5SMatthias Ringwald /**
64*1b2596b5SMatthias Ringwald * \brief boolean signalling that the sysclk_init is done.
65*1b2596b5SMatthias Ringwald */
66*1b2596b5SMatthias Ringwald uint32_t sysclk_initialized = 0;
67*1b2596b5SMatthias Ringwald #endif
68*1b2596b5SMatthias Ringwald
69*1b2596b5SMatthias Ringwald /**
70*1b2596b5SMatthias Ringwald * \brief Set system clock prescaler configuration
71*1b2596b5SMatthias Ringwald *
72*1b2596b5SMatthias Ringwald * This function will change the system clock prescaler configuration to
73*1b2596b5SMatthias Ringwald * match the parameters.
74*1b2596b5SMatthias Ringwald *
75*1b2596b5SMatthias Ringwald * \note The parameters to this function are device-specific.
76*1b2596b5SMatthias Ringwald *
77*1b2596b5SMatthias Ringwald * \param ul_pres The CPU clock will be divided by \f$2^{mck\_pres}\f$
78*1b2596b5SMatthias Ringwald */
sysclk_set_prescalers(uint32_t ul_pres)79*1b2596b5SMatthias Ringwald void sysclk_set_prescalers(uint32_t ul_pres)
80*1b2596b5SMatthias Ringwald {
81*1b2596b5SMatthias Ringwald pmc_mck_set_prescaler(ul_pres);
82*1b2596b5SMatthias Ringwald SystemCoreClockUpdate();
83*1b2596b5SMatthias Ringwald }
84*1b2596b5SMatthias Ringwald
85*1b2596b5SMatthias Ringwald /**
86*1b2596b5SMatthias Ringwald * \brief Change the source of the main system clock.
87*1b2596b5SMatthias Ringwald *
88*1b2596b5SMatthias Ringwald * \param ul_src The new system clock source. Must be one of the constants
89*1b2596b5SMatthias Ringwald * from the <em>System Clock Sources</em> section.
90*1b2596b5SMatthias Ringwald */
sysclk_set_source(uint32_t ul_src)91*1b2596b5SMatthias Ringwald void sysclk_set_source(uint32_t ul_src)
92*1b2596b5SMatthias Ringwald {
93*1b2596b5SMatthias Ringwald switch (ul_src) {
94*1b2596b5SMatthias Ringwald case SYSCLK_SRC_SLCK_RC:
95*1b2596b5SMatthias Ringwald case SYSCLK_SRC_SLCK_XTAL:
96*1b2596b5SMatthias Ringwald case SYSCLK_SRC_SLCK_BYPASS:
97*1b2596b5SMatthias Ringwald pmc_mck_set_source(PMC_MCKR_CSS_SLOW_CLK);
98*1b2596b5SMatthias Ringwald break;
99*1b2596b5SMatthias Ringwald
100*1b2596b5SMatthias Ringwald case SYSCLK_SRC_MAINCK_4M_RC:
101*1b2596b5SMatthias Ringwald case SYSCLK_SRC_MAINCK_8M_RC:
102*1b2596b5SMatthias Ringwald case SYSCLK_SRC_MAINCK_12M_RC:
103*1b2596b5SMatthias Ringwald case SYSCLK_SRC_MAINCK_XTAL:
104*1b2596b5SMatthias Ringwald case SYSCLK_SRC_MAINCK_BYPASS:
105*1b2596b5SMatthias Ringwald pmc_mck_set_source(PMC_MCKR_CSS_MAIN_CLK);
106*1b2596b5SMatthias Ringwald break;
107*1b2596b5SMatthias Ringwald
108*1b2596b5SMatthias Ringwald case SYSCLK_SRC_PLLACK:
109*1b2596b5SMatthias Ringwald pmc_mck_set_source(PMC_MCKR_CSS_PLLA_CLK);
110*1b2596b5SMatthias Ringwald break;
111*1b2596b5SMatthias Ringwald
112*1b2596b5SMatthias Ringwald case SYSCLK_SRC_UPLLCK:
113*1b2596b5SMatthias Ringwald pmc_mck_set_source(PMC_MCKR_CSS_UPLL_CLK);
114*1b2596b5SMatthias Ringwald break;
115*1b2596b5SMatthias Ringwald }
116*1b2596b5SMatthias Ringwald
117*1b2596b5SMatthias Ringwald SystemCoreClockUpdate();
118*1b2596b5SMatthias Ringwald }
119*1b2596b5SMatthias Ringwald
120*1b2596b5SMatthias Ringwald #if defined(CONFIG_USBCLK_SOURCE) || defined(__DOXYGEN__)
121*1b2596b5SMatthias Ringwald /**
122*1b2596b5SMatthias Ringwald * \brief Enable USB clock.
123*1b2596b5SMatthias Ringwald *
124*1b2596b5SMatthias Ringwald * \note The SAMV71 UDP hardware interprets div as div+1. For readability the hardware div+1
125*1b2596b5SMatthias Ringwald * is hidden in this implementation. Use div as div effective value.
126*1b2596b5SMatthias Ringwald *
127*1b2596b5SMatthias Ringwald * \param pll_id Source of the USB clock.
128*1b2596b5SMatthias Ringwald * \param div Actual clock divisor. Must be superior to 0.
129*1b2596b5SMatthias Ringwald */
sysclk_enable_usb(void)130*1b2596b5SMatthias Ringwald void sysclk_enable_usb(void)
131*1b2596b5SMatthias Ringwald {
132*1b2596b5SMatthias Ringwald Assert(CONFIG_USBCLK_DIV > 0);
133*1b2596b5SMatthias Ringwald
134*1b2596b5SMatthias Ringwald #ifdef CONFIG_PLL0_SOURCE
135*1b2596b5SMatthias Ringwald if (CONFIG_USBCLK_SOURCE == USBCLK_SRC_PLL0) {
136*1b2596b5SMatthias Ringwald struct pll_config pllcfg;
137*1b2596b5SMatthias Ringwald
138*1b2596b5SMatthias Ringwald pll_enable_source(CONFIG_PLL0_SOURCE);
139*1b2596b5SMatthias Ringwald pll_config_defaults(&pllcfg, 0);
140*1b2596b5SMatthias Ringwald pll_enable(&pllcfg, 0);
141*1b2596b5SMatthias Ringwald pll_wait_for_lock(0);
142*1b2596b5SMatthias Ringwald pmc_switch_udpck_to_pllack(CONFIG_USBCLK_DIV - 1);
143*1b2596b5SMatthias Ringwald pmc_enable_udpck();
144*1b2596b5SMatthias Ringwald return;
145*1b2596b5SMatthias Ringwald }
146*1b2596b5SMatthias Ringwald #endif
147*1b2596b5SMatthias Ringwald
148*1b2596b5SMatthias Ringwald if (CONFIG_USBCLK_SOURCE == USBCLK_SRC_UPLL) {
149*1b2596b5SMatthias Ringwald
150*1b2596b5SMatthias Ringwald pmc_enable_upll_clock();
151*1b2596b5SMatthias Ringwald pmc_switch_udpck_to_upllck(CONFIG_USBCLK_DIV - 1);
152*1b2596b5SMatthias Ringwald pmc_enable_udpck();
153*1b2596b5SMatthias Ringwald return;
154*1b2596b5SMatthias Ringwald }
155*1b2596b5SMatthias Ringwald }
156*1b2596b5SMatthias Ringwald
157*1b2596b5SMatthias Ringwald /**
158*1b2596b5SMatthias Ringwald * \brief Disable the USB clock.
159*1b2596b5SMatthias Ringwald *
160*1b2596b5SMatthias Ringwald * \note This implementation does not switch off the PLL, it just turns off the USB clock.
161*1b2596b5SMatthias Ringwald */
sysclk_disable_usb(void)162*1b2596b5SMatthias Ringwald void sysclk_disable_usb(void)
163*1b2596b5SMatthias Ringwald {
164*1b2596b5SMatthias Ringwald pmc_disable_udpck();
165*1b2596b5SMatthias Ringwald }
166*1b2596b5SMatthias Ringwald #endif // CONFIG_USBCLK_SOURCE
167*1b2596b5SMatthias Ringwald
sysclk_init(void)168*1b2596b5SMatthias Ringwald void sysclk_init(void)
169*1b2596b5SMatthias Ringwald {
170*1b2596b5SMatthias Ringwald struct pll_config pllcfg;
171*1b2596b5SMatthias Ringwald
172*1b2596b5SMatthias Ringwald /* Set flash wait state to max in case the below clock switching. */
173*1b2596b5SMatthias Ringwald system_init_flash(CHIP_FREQ_CPU_MAX);
174*1b2596b5SMatthias Ringwald
175*1b2596b5SMatthias Ringwald /* Config system clock setting */
176*1b2596b5SMatthias Ringwald if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_SLCK_RC) {
177*1b2596b5SMatthias Ringwald osc_enable(OSC_SLCK_32K_RC);
178*1b2596b5SMatthias Ringwald osc_wait_ready(OSC_SLCK_32K_RC);
179*1b2596b5SMatthias Ringwald pmc_switch_mck_to_sclk(CONFIG_SYSCLK_PRES);
180*1b2596b5SMatthias Ringwald }
181*1b2596b5SMatthias Ringwald
182*1b2596b5SMatthias Ringwald else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_SLCK_XTAL) {
183*1b2596b5SMatthias Ringwald osc_enable(OSC_SLCK_32K_XTAL);
184*1b2596b5SMatthias Ringwald osc_wait_ready(OSC_SLCK_32K_XTAL);
185*1b2596b5SMatthias Ringwald pmc_switch_mck_to_sclk(CONFIG_SYSCLK_PRES);
186*1b2596b5SMatthias Ringwald }
187*1b2596b5SMatthias Ringwald
188*1b2596b5SMatthias Ringwald else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_SLCK_BYPASS) {
189*1b2596b5SMatthias Ringwald osc_enable(OSC_SLCK_32K_BYPASS);
190*1b2596b5SMatthias Ringwald osc_wait_ready(OSC_SLCK_32K_BYPASS);
191*1b2596b5SMatthias Ringwald pmc_switch_mck_to_sclk(CONFIG_SYSCLK_PRES);
192*1b2596b5SMatthias Ringwald }
193*1b2596b5SMatthias Ringwald
194*1b2596b5SMatthias Ringwald else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_4M_RC) {
195*1b2596b5SMatthias Ringwald /* Already running from SYSCLK_SRC_MAINCK_4M_RC */
196*1b2596b5SMatthias Ringwald }
197*1b2596b5SMatthias Ringwald
198*1b2596b5SMatthias Ringwald else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_8M_RC) {
199*1b2596b5SMatthias Ringwald osc_enable(OSC_MAINCK_8M_RC);
200*1b2596b5SMatthias Ringwald osc_wait_ready(OSC_MAINCK_8M_RC);
201*1b2596b5SMatthias Ringwald pmc_switch_mck_to_mainck(CONFIG_SYSCLK_PRES);
202*1b2596b5SMatthias Ringwald }
203*1b2596b5SMatthias Ringwald
204*1b2596b5SMatthias Ringwald else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_12M_RC) {
205*1b2596b5SMatthias Ringwald osc_enable(OSC_MAINCK_12M_RC);
206*1b2596b5SMatthias Ringwald osc_wait_ready(OSC_MAINCK_12M_RC);
207*1b2596b5SMatthias Ringwald pmc_switch_mck_to_mainck(CONFIG_SYSCLK_PRES);
208*1b2596b5SMatthias Ringwald }
209*1b2596b5SMatthias Ringwald
210*1b2596b5SMatthias Ringwald else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_XTAL) {
211*1b2596b5SMatthias Ringwald osc_enable(OSC_MAINCK_XTAL);
212*1b2596b5SMatthias Ringwald osc_wait_ready(OSC_MAINCK_XTAL);
213*1b2596b5SMatthias Ringwald pmc_switch_mck_to_mainck(CONFIG_SYSCLK_PRES);
214*1b2596b5SMatthias Ringwald }
215*1b2596b5SMatthias Ringwald
216*1b2596b5SMatthias Ringwald else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_MAINCK_BYPASS) {
217*1b2596b5SMatthias Ringwald osc_enable(OSC_MAINCK_BYPASS);
218*1b2596b5SMatthias Ringwald osc_wait_ready(OSC_MAINCK_BYPASS);
219*1b2596b5SMatthias Ringwald pmc_switch_mck_to_mainck(CONFIG_SYSCLK_PRES);
220*1b2596b5SMatthias Ringwald }
221*1b2596b5SMatthias Ringwald
222*1b2596b5SMatthias Ringwald #ifdef CONFIG_PLL0_SOURCE
223*1b2596b5SMatthias Ringwald else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_PLLACK) {
224*1b2596b5SMatthias Ringwald pll_enable_source(CONFIG_PLL0_SOURCE);
225*1b2596b5SMatthias Ringwald pll_config_defaults(&pllcfg, 0);
226*1b2596b5SMatthias Ringwald pll_enable(&pllcfg, 0);
227*1b2596b5SMatthias Ringwald pll_wait_for_lock(0);
228*1b2596b5SMatthias Ringwald pmc_mck_set_division(CONFIG_SYSCLK_DIV);
229*1b2596b5SMatthias Ringwald pmc_switch_mck_to_pllack(CONFIG_SYSCLK_PRES);
230*1b2596b5SMatthias Ringwald }
231*1b2596b5SMatthias Ringwald #endif
232*1b2596b5SMatthias Ringwald
233*1b2596b5SMatthias Ringwald else if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_UPLLCK) {
234*1b2596b5SMatthias Ringwald pll_enable_source(CONFIG_PLL1_SOURCE);
235*1b2596b5SMatthias Ringwald pll_config_defaults(&pllcfg, 1);
236*1b2596b5SMatthias Ringwald pll_enable(&pllcfg, 1);
237*1b2596b5SMatthias Ringwald pll_wait_for_lock(1);
238*1b2596b5SMatthias Ringwald pmc_mck_set_division(CONFIG_SYSCLK_DIV);
239*1b2596b5SMatthias Ringwald pmc_switch_mck_to_upllck(CONFIG_SYSCLK_PRES);
240*1b2596b5SMatthias Ringwald }
241*1b2596b5SMatthias Ringwald /* Update the SystemFrequency variable */
242*1b2596b5SMatthias Ringwald SystemCoreClockUpdate();
243*1b2596b5SMatthias Ringwald
244*1b2596b5SMatthias Ringwald /* Set a flash wait state depending on the new cpu frequency */
245*1b2596b5SMatthias Ringwald system_init_flash(sysclk_get_cpu_hz());
246*1b2596b5SMatthias Ringwald
247*1b2596b5SMatthias Ringwald #if (defined CONFIG_SYSCLK_DEFAULT_RETURNS_SLOW_OSC)
248*1b2596b5SMatthias Ringwald /* Signal that the internal frequencies are setup */
249*1b2596b5SMatthias Ringwald sysclk_initialized = 1;
250*1b2596b5SMatthias Ringwald #endif
251*1b2596b5SMatthias Ringwald }
252*1b2596b5SMatthias Ringwald
253*1b2596b5SMatthias Ringwald //! @}
254*1b2596b5SMatthias Ringwald
255*1b2596b5SMatthias Ringwald /// @cond 0
256*1b2596b5SMatthias Ringwald /**INDENT-OFF**/
257*1b2596b5SMatthias Ringwald #ifdef __cplusplus
258*1b2596b5SMatthias Ringwald }
259*1b2596b5SMatthias Ringwald #endif
260*1b2596b5SMatthias Ringwald /**INDENT-ON**/
261*1b2596b5SMatthias Ringwald /// @endcond
262