1 /* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
2
3 /*This file has been prepared for Doxygen automatic documentation generation.*/
4 /*! \file *********************************************************************
5 *
6 * \brief Power Manager clocks configuration helper.
7 *
8 *
9 * - Compiler: IAR EWAVR32 and GNU GCC for AVR32
10 * - Supported devices: All AVR32 devices.
11 * - AppNote:
12 *
13 * \author Atmel Corporation: http://www.atmel.com \n
14 * Support and FAQ: http://support.atmel.no/
15 *
16 *****************************************************************************/
17
18 /* Copyright (c) 2009 Atmel Corporation. All rights reserved.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions are met:
22 *
23 * 1. Redistributions of source code must retain the above copyright notice, this
24 * list of conditions and the following disclaimer.
25 *
26 * 2. Redistributions in binary form must reproduce the above copyright notice,
27 * this list of conditions and the following disclaimer in the documentation
28 * and/or other materials provided with the distribution.
29 *
30 * 3. The name of Atmel may not be used to endorse or promote products derived
31 * from this software without specific prior written permission.
32 *
33 * 4. This software may only be redistributed and used in connection with an Atmel
34 * AVR product.
35 *
36 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
38 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
39 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
40 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
45 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
46 *
47 */
48
49 #include <string.h>
50 #include "compiler.h"
51 #include "pm.h"
52
53 extern void flashc_set_wait_state(unsigned int wait_state);
54 #if (defined AVR32_FLASHC_210_H_INCLUDED)
55 extern void flashc_issue_command(unsigned int command, int page_number);
56 #endif
57
58
59 #define PM_MAX_MUL ((1 << AVR32_PM_PLL0_PLLMUL_SIZE) - 1)
60
61
pm_configure_clocks(pm_freq_param_t * param)62 int pm_configure_clocks(pm_freq_param_t *param)
63 {
64 // Supported frequencies:
65 // Fosc0 mul div PLL div2_en cpu_f pba_f Comment
66 // 12 15 1 192 1 12 12
67 // 12 9 3 40 1 20 20 PLL out of spec
68 // 12 15 1 192 1 24 12
69 // 12 9 1 120 1 30 15
70 // 12 9 3 40 0 40 20 PLL out of spec
71 // 12 15 1 192 1 48 12
72 // 12 15 1 192 1 48 24
73 // 12 8 1 108 1 54 27
74 // 12 9 1 120 1 60 15
75 // 12 9 1 120 1 60 30
76 // 12 10 1 132 1 66 16.5
77 //
78 unsigned long in_cpu_f = param->cpu_f;
79 unsigned long in_osc0_f = param->osc0_f;
80 unsigned long mul, div, div2_en = 0, div2_cpu = 0, div2_pba = 0;
81 unsigned long pll_freq, rest;
82 Bool b_div2_pba, b_div2_cpu;
83
84 // Switch to external Oscillator 0
85 pm_switch_to_osc0(&AVR32_PM, in_osc0_f, param->osc0_startup);
86
87 // Start with CPU freq config
88 if (in_cpu_f == in_osc0_f)
89 {
90 param->cpu_f = in_osc0_f;
91 param->pba_f = in_osc0_f;
92 return PM_FREQ_STATUS_OK;
93 }
94 else if (in_cpu_f < in_osc0_f)
95 {
96 // TBD
97 }
98
99 rest = in_cpu_f % in_osc0_f;
100
101 for (div = 1; div < 32; div++)
102 {
103 if ((div * rest) % in_osc0_f == 0)
104 break;
105 }
106 if (div == 32)
107 return PM_FREQ_STATUS_FAIL;
108
109 mul = (in_cpu_f * div) / in_osc0_f;
110
111 if (mul > PM_MAX_MUL)
112 return PM_FREQ_STATUS_FAIL;
113
114 // export 2power from PLL div to div2_cpu
115 while (!(div % 2))
116 {
117 div /= 2;
118 div2_cpu++;
119 }
120
121 // Here we know the mul and div parameter of the PLL config.
122 // . Check out if the PLL has a valid in_cpu_f.
123 // . Try to have for the PLL frequency (VCO output) the highest possible value
124 // to reduce jitter.
125 while (in_osc0_f * 2 * mul / div < AVR32_PM_PLL_VCO_RANGE0_MAX_FREQ)
126 {
127 if (2 * mul > PM_MAX_MUL)
128 break;
129 mul *= 2;
130 div2_cpu++;
131 }
132
133 if (div2_cpu != 0)
134 {
135 div2_cpu--;
136 div2_en = 1;
137 }
138
139 pll_freq = in_osc0_f * mul / (div * (1 << div2_en));
140
141 // Update real CPU Frequency
142 param->cpu_f = pll_freq / (1 << div2_cpu);
143 mul--;
144
145 pm_pll_setup(&AVR32_PM
146 , 0 // pll
147 , mul // mul
148 , div // div
149 , 0 // osc
150 , 16 // lockcount
151 );
152
153 pm_pll_set_option(&AVR32_PM
154 , 0 // pll
155 // PLL clock is lower than 160MHz: need to set pllopt.
156 , (pll_freq < AVR32_PM_PLL_VCO_RANGE0_MIN_FREQ) ? 1 : 0 // pll_freq
157 , div2_en // pll_div2
158 , 0 // pll_wbwdisable
159 );
160
161 rest = pll_freq;
162 while (rest > AVR32_PM_PBA_MAX_FREQ ||
163 rest != param->pba_f)
164 {
165 div2_pba++;
166 rest = pll_freq / (1 << div2_pba);
167 if (rest < param->pba_f)
168 break;
169 }
170
171 // Update real PBA Frequency
172 param->pba_f = pll_freq / (1 << div2_pba);
173
174 // Enable PLL0
175 pm_pll_enable(&AVR32_PM, 0);
176
177 // Wait for PLL0 locked
178 pm_wait_for_pll0_locked(&AVR32_PM);
179
180 if (div2_cpu)
181 {
182 b_div2_cpu = TRUE;
183 div2_cpu--;
184 }
185 else
186 b_div2_cpu = FALSE;
187
188 if (div2_pba)
189 {
190 b_div2_pba = TRUE;
191 div2_pba--;
192 }
193 else
194 b_div2_pba = FALSE;
195
196 pm_cksel(&AVR32_PM
197 , b_div2_pba, div2_pba // PBA
198 , b_div2_cpu, div2_cpu // PBB
199 , b_div2_cpu, div2_cpu // HSB
200 );
201
202 if (param->cpu_f > AVR32_FLASHC_FWS_0_MAX_FREQ)
203 {
204 flashc_set_wait_state(1);
205 #if (defined AVR32_FLASHC_210_H_INCLUDED)
206 if (param->cpu_f > AVR32_FLASHC_HSEN_FWS_1_MAX_FREQ)
207 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSEN, -1);
208 else
209 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSDIS, -1);
210 #endif
211 }
212 else
213 {
214 flashc_set_wait_state(0);
215 #if (defined AVR32_FLASHC_210_H_INCLUDED)
216 if (param->cpu_f > AVR32_FLASHC_HSEN_FWS_0_MAX_FREQ)
217 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSEN, -1);
218 else
219 flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSDIS, -1);
220 #endif
221 }
222
223 pm_switch_to_clock(&AVR32_PM, AVR32_PM_MCCTRL_MCSEL_PLL0);
224
225 return PM_FREQ_STATUS_OK;
226 }
227
228
pm_configure_usb_clock(void)229 void pm_configure_usb_clock(void)
230 {
231 #if UC3A3
232
233 // Setup USB GCLK.
234 pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_USBB, // gc
235 0, // osc_or_pll: use Osc (if 0) or PLL (if 1)
236 0, // pll_osc: select Osc0/PLL0 or Osc1/PLL1
237 0, // diven
238 0); // div
239
240 // Enable USB GCLK.
241 pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_USBB);
242 #else
243 // Use 12MHz from OSC0 and generate 96 MHz
244 pm_pll_setup(&AVR32_PM, 1, // pll.
245 7, // mul.
246 1, // div.
247 0, // osc.
248 16); // lockcount.
249
250 pm_pll_set_option(&AVR32_PM, 1, // pll.
251 1, // pll_freq: choose the range 80-180MHz.
252 1, // pll_div2.
253 0); // pll_wbwdisable.
254
255 // start PLL1 and wait forl lock
256 pm_pll_enable(&AVR32_PM, 1);
257
258 // Wait for PLL1 locked.
259 pm_wait_for_pll1_locked(&AVR32_PM);
260
261 pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_USBB, // gc.
262 1, // osc_or_pll: use Osc (if 0) or PLL (if 1).
263 1, // pll_osc: select Osc0/PLL0 or Osc1/PLL1.
264 0, // diven.
265 0); // div.
266 pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_USBB);
267 #endif
268 }
269