1 /* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
\r
3 /*This file has been prepared for Doxygen automatic documentation generation.*/
\r
4 /*! \file *********************************************************************
\r
6 * \brief Power Manager clocks configuration helper.
\r
9 * - Compiler: IAR EWAVR32 and GNU GCC for AVR32
\r
10 * - Supported devices: All AVR32 devices.
\r
13 * \author Atmel Corporation: http://www.atmel.com \n
\r
14 * Support and FAQ: http://support.atmel.no/
\r
16 *****************************************************************************/
\r
18 /* Copyright (c) 2009 Atmel Corporation. All rights reserved.
\r
20 * Redistribution and use in source and binary forms, with or without
\r
21 * modification, are permitted provided that the following conditions are met:
\r
23 * 1. Redistributions of source code must retain the above copyright notice, this
\r
24 * list of conditions and the following disclaimer.
\r
26 * 2. Redistributions in binary form must reproduce the above copyright notice,
\r
27 * this list of conditions and the following disclaimer in the documentation
\r
28 * and/or other materials provided with the distribution.
\r
30 * 3. The name of Atmel may not be used to endorse or promote products derived
\r
31 * from this software without specific prior written permission.
\r
33 * 4. This software may only be redistributed and used in connection with an Atmel
\r
36 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
\r
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
38 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
39 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
\r
40 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
\r
41 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
\r
42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
\r
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
\r
44 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
\r
45 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
\r
50 #include "compiler.h"
\r
53 extern void flashc_set_wait_state(unsigned int wait_state);
\r
54 #if (defined AVR32_FLASHC_210_H_INCLUDED)
\r
55 extern void flashc_issue_command(unsigned int command, int page_number);
\r
59 #define PM_MAX_MUL ((1 << AVR32_PM_PLL0_PLLMUL_SIZE) - 1)
\r
62 int pm_configure_clocks(pm_freq_param_t *param)
\r
64 // Supported frequencies:
\r
65 // Fosc0 mul div PLL div2_en cpu_f pba_f Comment
\r
66 // 12 15 1 192 1 12 12
\r
67 // 12 9 3 40 1 20 20 PLL out of spec
\r
68 // 12 15 1 192 1 24 12
\r
69 // 12 9 1 120 1 30 15
\r
70 // 12 9 3 40 0 40 20 PLL out of spec
\r
71 // 12 15 1 192 1 48 12
\r
72 // 12 15 1 192 1 48 24
\r
73 // 12 8 1 108 1 54 27
\r
74 // 12 9 1 120 1 60 15
\r
75 // 12 9 1 120 1 60 30
\r
76 // 12 10 1 132 1 66 16.5
\r
78 unsigned long in_cpu_f = param->cpu_f;
\r
79 unsigned long in_osc0_f = param->osc0_f;
\r
80 unsigned long mul, div, div2_en = 0, div2_cpu = 0, div2_pba = 0;
\r
81 unsigned long pll_freq, rest;
\r
82 Bool b_div2_pba, b_div2_cpu;
\r
84 // Switch to external Oscillator 0
\r
85 pm_switch_to_osc0(&AVR32_PM, in_osc0_f, param->osc0_startup);
\r
87 // Start with CPU freq config
\r
88 if (in_cpu_f == in_osc0_f)
\r
90 param->cpu_f = in_osc0_f;
\r
91 param->pba_f = in_osc0_f;
\r
92 return PM_FREQ_STATUS_OK;
\r
94 else if (in_cpu_f < in_osc0_f)
\r
99 rest = in_cpu_f % in_osc0_f;
\r
101 for (div = 1; div < 32; div++)
\r
103 if ((div * rest) % in_osc0_f == 0)
\r
107 return PM_FREQ_STATUS_FAIL;
\r
109 mul = (in_cpu_f * div) / in_osc0_f;
\r
111 if (mul > PM_MAX_MUL)
\r
112 return PM_FREQ_STATUS_FAIL;
\r
114 // export 2power from PLL div to div2_cpu
\r
121 // Here we know the mul and div parameter of the PLL config.
\r
122 // . Check out if the PLL has a valid in_cpu_f.
\r
123 // . Try to have for the PLL frequency (VCO output) the highest possible value
\r
124 // to reduce jitter.
\r
125 while (in_osc0_f * 2 * mul / div < AVR32_PM_PLL_VCO_RANGE0_MAX_FREQ)
\r
127 if (2 * mul > PM_MAX_MUL)
\r
139 pll_freq = in_osc0_f * mul / (div * (1 << div2_en));
\r
141 // Update real CPU Frequency
\r
142 param->cpu_f = pll_freq / (1 << div2_cpu);
\r
145 pm_pll_setup(&AVR32_PM
\r
153 pm_pll_set_option(&AVR32_PM
\r
155 // PLL clock is lower than 160MHz: need to set pllopt.
\r
156 , (pll_freq < AVR32_PM_PLL_VCO_RANGE0_MIN_FREQ) ? 1 : 0 // pll_freq
\r
157 , div2_en // pll_div2
\r
158 , 0 // pll_wbwdisable
\r
162 while (rest > AVR32_PM_PBA_MAX_FREQ ||
\r
163 rest != param->pba_f)
\r
166 rest = pll_freq / (1 << div2_pba);
\r
167 if (rest < param->pba_f)
\r
171 // Update real PBA Frequency
\r
172 param->pba_f = pll_freq / (1 << div2_pba);
\r
175 pm_pll_enable(&AVR32_PM, 0);
\r
177 // Wait for PLL0 locked
\r
178 pm_wait_for_pll0_locked(&AVR32_PM);
\r
186 b_div2_cpu = FALSE;
\r
194 b_div2_pba = FALSE;
\r
197 , b_div2_pba, div2_pba // PBA
\r
198 , b_div2_cpu, div2_cpu // PBB
\r
199 , b_div2_cpu, div2_cpu // HSB
\r
202 if (param->cpu_f > AVR32_FLASHC_FWS_0_MAX_FREQ)
\r
204 flashc_set_wait_state(1);
\r
205 #if (defined AVR32_FLASHC_210_H_INCLUDED)
\r
206 if (param->cpu_f > AVR32_FLASHC_HSEN_FWS_1_MAX_FREQ)
\r
207 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSEN, -1);
\r
209 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSDIS, -1);
\r
214 flashc_set_wait_state(0);
\r
215 #if (defined AVR32_FLASHC_210_H_INCLUDED)
\r
216 if (param->cpu_f > AVR32_FLASHC_HSEN_FWS_0_MAX_FREQ)
\r
217 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSEN, -1);
\r
219 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSDIS, -1);
\r
223 pm_switch_to_clock(&AVR32_PM, AVR32_PM_MCCTRL_MCSEL_PLL0);
\r
225 return PM_FREQ_STATUS_OK;
\r
229 void pm_configure_usb_clock(void)
\r
234 pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_USBB, // gc
\r
235 0, // osc_or_pll: use Osc (if 0) or PLL (if 1)
\r
236 0, // pll_osc: select Osc0/PLL0 or Osc1/PLL1
\r
240 // Enable USB GCLK.
\r
241 pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_USBB);
\r
243 // Use 12MHz from OSC0 and generate 96 MHz
\r
244 pm_pll_setup(&AVR32_PM, 1, // pll.
\r
250 pm_pll_set_option(&AVR32_PM, 1, // pll.
\r
251 1, // pll_freq: choose the range 80-180MHz.
\r
253 0); // pll_wbwdisable.
\r
255 // start PLL1 and wait forl lock
\r
256 pm_pll_enable(&AVR32_PM, 1);
\r
258 // Wait for PLL1 locked.
\r
259 pm_wait_for_pll1_locked(&AVR32_PM);
\r
261 pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_USBB, // gc.
\r
262 1, // osc_or_pll: use Osc (if 0) or PLL (if 1).
\r
263 1, // pll_osc: select Osc0/PLL0 or Osc1/PLL1.
\r
266 pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_USBB);
\r