]> git.sur5r.net Git - freertos/blob - Demo/AVR32_UC3A_GCC/Atmel_SW_Framework/DRIVERS/PM/pm_conf_clocks.c
Temporarily revert the AVR32 port back to the V6.0.5 files. Work will continue on...
[freertos] / Demo / AVR32_UC3A_GCC / Atmel_SW_Framework / DRIVERS / PM / pm_conf_clocks.c
1 /* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */\r
2
3 /*This file has been prepared for Doxygen automatic documentation generation.*/\r
4 /*! \file *********************************************************************\r
5  *\r
6  * \brief Power Manager clocks configuration helper.\r
7  *\r
8  *\r
9  * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32\r
10  * - Supported devices:  All AVR32 devices.\r
11  * - AppNote:\r
12  *\r
13  * \author               Atmel Corporation: http://www.atmel.com \n\r
14  *                       Support and FAQ: http://support.atmel.no/\r
15  *\r
16  *****************************************************************************/\r
17 \r
18 /* Copyright (c) 2009 Atmel Corporation. All rights reserved.\r
19  *\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
22  *\r
23  * 1. Redistributions of source code must retain the above copyright notice, this\r
24  * list of conditions and the following disclaimer.\r
25  *\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
29  *\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
32  *\r
33  * 4. This software may only be redistributed and used in connection with an Atmel\r
34  * AVR product.\r
35  *\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
46  *\r
47  */\r
48 \r
49 #include <string.h>\r
50 #include "compiler.h"\r
51 #include "pm.h"\r
52 \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
56 #endif\r
57 \r
58 \r
59 #define PM_MAX_MUL                ((1 << AVR32_PM_PLL0_PLLMUL_SIZE) - 1)\r
60 \r
61 \r
62 int pm_configure_clocks(pm_freq_param_t *param)\r
63 {\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
77   //\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
83 \r
84   // Switch to external Oscillator 0\r
85   pm_switch_to_osc0(&AVR32_PM, in_osc0_f, param->osc0_startup);\r
86 \r
87   // Start with CPU freq config\r
88   if (in_cpu_f == in_osc0_f)\r
89   {\r
90     param->cpu_f = in_osc0_f;\r
91     param->pba_f = in_osc0_f;\r
92     return PM_FREQ_STATUS_OK;\r
93   }\r
94   else if (in_cpu_f < in_osc0_f)\r
95   {\r
96     // TBD\r
97   }\r
98 \r
99   rest = in_cpu_f % in_osc0_f;\r
100 \r
101   for (div = 1; div < 32; div++)\r
102   {\r
103     if ((div * rest) % in_osc0_f == 0)\r
104       break;\r
105   }\r
106   if (div == 32)\r
107     return PM_FREQ_STATUS_FAIL;\r
108 \r
109   mul = (in_cpu_f * div) / in_osc0_f;\r
110 \r
111   if (mul > PM_MAX_MUL)\r
112     return PM_FREQ_STATUS_FAIL;\r
113 \r
114   // export 2power from PLL div to div2_cpu\r
115   while (!(div % 2))\r
116   {\r
117     div /= 2;\r
118     div2_cpu++;\r
119   }\r
120 \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
126   {\r
127     if (2 * mul > PM_MAX_MUL)\r
128       break;\r
129     mul *= 2;\r
130     div2_cpu++;\r
131   }\r
132 \r
133   if (div2_cpu != 0)\r
134   {\r
135     div2_cpu--;\r
136     div2_en = 1;\r
137   }\r
138 \r
139   pll_freq = in_osc0_f * mul / (div * (1 << div2_en));\r
140 \r
141   // Update real CPU Frequency\r
142   param->cpu_f = pll_freq / (1 << div2_cpu);\r
143   mul--;\r
144 \r
145   pm_pll_setup(&AVR32_PM\r
146   , 0   // pll\r
147   , mul // mul\r
148   , div // div\r
149   , 0   // osc\r
150   , 16  // lockcount\r
151   );\r
152 \r
153   pm_pll_set_option(&AVR32_PM\r
154   , 0 // pll\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
159   );\r
160 \r
161   rest = pll_freq;\r
162   while (rest > AVR32_PM_PBA_MAX_FREQ ||\r
163          rest != param->pba_f)\r
164   {\r
165     div2_pba++;\r
166     rest = pll_freq / (1 << div2_pba);\r
167     if (rest < param->pba_f)\r
168       break;\r
169   }\r
170 \r
171   // Update real PBA Frequency\r
172   param->pba_f = pll_freq / (1 << div2_pba);\r
173 \r
174   // Enable PLL0\r
175   pm_pll_enable(&AVR32_PM, 0);\r
176 \r
177   // Wait for PLL0 locked\r
178   pm_wait_for_pll0_locked(&AVR32_PM);\r
179 \r
180   if (div2_cpu)\r
181   {\r
182     b_div2_cpu = TRUE;\r
183     div2_cpu--;\r
184   }\r
185   else\r
186     b_div2_cpu = FALSE;\r
187 \r
188   if (div2_pba)\r
189   {\r
190     b_div2_pba = TRUE;\r
191     div2_pba--;\r
192   }\r
193   else\r
194     b_div2_pba = FALSE;\r
195 \r
196   pm_cksel(&AVR32_PM\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
200   );\r
201 \r
202   if (param->cpu_f > AVR32_FLASHC_FWS_0_MAX_FREQ)\r
203   {\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
208     else\r
209       flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSDIS, -1);\r
210 #endif\r
211   }\r
212   else\r
213   {\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
218     else\r
219       flashc_issue_command(AVR32_FLASHC_FCMD_CMD_HSDIS, -1);\r
220 #endif\r
221   }\r
222 \r
223   pm_switch_to_clock(&AVR32_PM, AVR32_PM_MCCTRL_MCSEL_PLL0);\r
224 \r
225   return PM_FREQ_STATUS_OK;\r
226 }\r
227 \r
228 \r
229 void pm_configure_usb_clock(void)\r
230 {\r
231 #if UC3A3\r
232 \r
233   // Setup USB GCLK.\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
237                   0,                  // diven\r
238                   0);                 // div\r
239 \r
240   // Enable USB GCLK.\r
241   pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_USBB);\r
242 #else\r
243   // Use 12MHz from OSC0 and generate 96 MHz\r
244   pm_pll_setup(&AVR32_PM, 1,  // pll.\r
245           7,   // mul.\r
246           1,   // div.\r
247           0,   // osc.\r
248           16); // lockcount.\r
249 \r
250   pm_pll_set_option(&AVR32_PM, 1, // pll.\r
251           1,  // pll_freq: choose the range 80-180MHz.\r
252           1,  // pll_div2.\r
253           0); // pll_wbwdisable.\r
254 \r
255   // start PLL1 and wait forl lock\r
256   pm_pll_enable(&AVR32_PM, 1);\r
257 \r
258   // Wait for PLL1 locked.\r
259   pm_wait_for_pll1_locked(&AVR32_PM);\r
260 \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
264             0,  // diven.\r
265             0); // div.\r
266   pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_USBB);\r
267 #endif\r
268 }\r