]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/lwIP_AVR32_UC3/DRIVERS/PM/pm.c
Add FreeRTOS-Plus directory.
[freertos] / FreeRTOS / Demo / lwIP_AVR32_UC3 / DRIVERS / PM / pm.c
1 /*This file has been prepared for Doxygen automatic documentation generation.*/\r
2 /*! \file *********************************************************************\r
3  *\r
4  * \brief Power Manager driver.\r
5  *\r
6  *\r
7  * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32\r
8  * - Supported devices:  All AVR32 devices.\r
9  * - AppNote:\r
10  *\r
11  * \author               Atmel Corporation: http://www.atmel.com \n\r
12  *                       Support and FAQ: http://support.atmel.no/\r
13  *\r
14  *****************************************************************************/\r
15 \r
16 /* Copyright (c) 2007, Atmel Corporation All rights reserved.\r
17  *\r
18  * Redistribution and use in source and binary forms, with or without\r
19  * modification, are permitted provided that the following conditions are met:\r
20  *\r
21  * 1. Redistributions of source code must retain the above copyright notice,\r
22  * this list of conditions and the following disclaimer.\r
23  *\r
24  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
25  * this list of conditions and the following disclaimer in the documentation\r
26  * and/or other materials provided with the distribution.\r
27  *\r
28  * 3. The name of ATMEL may not be used to endorse or promote products derived\r
29  * from this software without specific prior written permission.\r
30  *\r
31  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
32  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
33  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND\r
34  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,\r
35  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
36  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
37  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
38  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
40  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
41  */\r
42 \r
43 \r
44 #include "pm.h"\r
45 \r
46 \r
47 /*! \name PM Writable Bit-Field Registers\r
48  */\r
49 //! @{\r
50 \r
51 typedef union\r
52 {\r
53   unsigned long                 mcctrl;\r
54   avr32_pm_mcctrl_t             MCCTRL;\r
55 } u_avr32_pm_mcctrl_t;\r
56 \r
57 typedef union\r
58 {\r
59   unsigned long                 cksel;\r
60   avr32_pm_cksel_t              CKSEL;\r
61 } u_avr32_pm_cksel_t;\r
62 \r
63 typedef union\r
64 {\r
65   unsigned long                 pll;\r
66   avr32_pm_pll_t                PLL;\r
67 } u_avr32_pm_pll_t;\r
68 \r
69 typedef union\r
70 {\r
71   unsigned long                 oscctrl0;\r
72   avr32_pm_oscctrl0_t           OSCCTRL0;\r
73 } u_avr32_pm_oscctrl0_t;\r
74 \r
75 typedef union\r
76 {\r
77   unsigned long                 oscctrl1;\r
78   avr32_pm_oscctrl1_t           OSCCTRL1;\r
79 } u_avr32_pm_oscctrl1_t;\r
80 \r
81 typedef union\r
82 {\r
83   unsigned long                 oscctrl32;\r
84   avr32_pm_oscctrl32_t          OSCCTRL32;\r
85 } u_avr32_pm_oscctrl32_t;\r
86 \r
87 typedef union\r
88 {\r
89   unsigned long                 ier;\r
90   avr32_pm_ier_t                IER;\r
91 } u_avr32_pm_ier_t;\r
92 \r
93 typedef union\r
94 {\r
95   unsigned long                 idr;\r
96   avr32_pm_idr_t                IDR;\r
97 } u_avr32_pm_idr_t;\r
98 \r
99 typedef union\r
100 {\r
101   unsigned long                 icr;\r
102   avr32_pm_icr_t                ICR;\r
103 } u_avr32_pm_icr_t;\r
104 \r
105 typedef union\r
106 {\r
107   unsigned long                 gcctrl;\r
108   avr32_pm_gcctrl_t             GCCTRL;\r
109 } u_avr32_pm_gcctrl_t;\r
110 \r
111 typedef union\r
112 {\r
113   unsigned long                 rccr;\r
114   avr32_pm_rccr_t               RCCR;\r
115 } u_avr32_pm_rccr_t;\r
116 \r
117 typedef union\r
118 {\r
119   unsigned long                 bgcr;\r
120   avr32_pm_bgcr_t               BGCR;\r
121 } u_avr32_pm_bgcr_t;\r
122 \r
123 typedef union\r
124 {\r
125   unsigned long                 vregcr;\r
126   avr32_pm_vregcr_t             VREGCR;\r
127 } u_avr32_pm_vregcr_t;\r
128 \r
129 typedef union\r
130 {\r
131   unsigned long                 bod;\r
132   avr32_pm_bod_t                BOD;\r
133 } u_avr32_pm_bod_t;\r
134 \r
135 //! @}\r
136 \r
137 \r
138 /*! \brief Sets the mode of the oscillator 0.\r
139  *\r
140  * \param pm Base address of the Power Manager (i.e. &AVR32_PM).\r
141  * \param mode Oscillator 0 mode (i.e. AVR32_PM_OSCCTRL0_MODE_x).\r
142  */\r
143 static void pm_set_osc0_mode(volatile avr32_pm_t *pm, unsigned int mode)\r
144 {\r
145   // Read\r
146   u_avr32_pm_oscctrl0_t u_avr32_pm_oscctrl0 = {pm->oscctrl0};\r
147   // Modify\r
148   u_avr32_pm_oscctrl0.OSCCTRL0.mode = mode;\r
149   // Write\r
150   pm->oscctrl0 = u_avr32_pm_oscctrl0.oscctrl0;\r
151 }\r
152 \r
153 \r
154 void pm_enable_osc0_ext_clock(volatile avr32_pm_t *pm)\r
155 {\r
156   pm_set_osc0_mode(pm, AVR32_PM_OSCCTRL0_MODE_EXT_CLOCK);\r
157 }\r
158 \r
159 \r
160 void pm_enable_osc0_crystal(volatile avr32_pm_t *pm, unsigned int fosc0)\r
161 {\r
162   pm_set_osc0_mode(pm, (fosc0 < 8000000) ? AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G2 :\r
163                                            AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G3);\r
164 }\r
165 \r
166 \r
167 void pm_enable_clk0(volatile avr32_pm_t *pm, unsigned int startup)\r
168 {\r
169   pm_enable_clk0_no_wait(pm, startup);\r
170   pm_wait_for_clk0_ready(pm);\r
171 }\r
172 \r
173 \r
174 void pm_disable_clk0(volatile avr32_pm_t *pm)\r
175 {\r
176   pm->mcctrl &= ~AVR32_PM_MCCTRL_OSC0EN_MASK;\r
177 }\r
178 \r
179 \r
180 void pm_enable_clk0_no_wait(volatile avr32_pm_t *pm, unsigned int startup)\r
181 {\r
182   // Read register\r
183   u_avr32_pm_oscctrl0_t u_avr32_pm_oscctrl0 = {pm->oscctrl0};\r
184   // Modify\r
185   u_avr32_pm_oscctrl0.OSCCTRL0.startup = startup;\r
186   // Write back\r
187   pm->oscctrl0 = u_avr32_pm_oscctrl0.oscctrl0;\r
188 \r
189   pm->mcctrl |= AVR32_PM_MCCTRL_OSC0EN_MASK;\r
190 }\r
191 \r
192 \r
193 void pm_wait_for_clk0_ready(volatile avr32_pm_t *pm)\r
194 {\r
195   while (!(pm->poscsr & AVR32_PM_POSCSR_OSC0RDY_MASK));\r
196 }\r
197 \r
198 \r
199 /*! \brief Sets the mode of the oscillator 1.\r
200  *\r
201  * \param pm Base address of the Power Manager (i.e. &AVR32_PM).\r
202  * \param mode Oscillator 1 mode (i.e. AVR32_PM_OSCCTRL1_MODE_x).\r
203  */\r
204 static void pm_set_osc1_mode(volatile avr32_pm_t *pm, unsigned int mode)\r
205 {\r
206   // Read\r
207   u_avr32_pm_oscctrl1_t u_avr32_pm_oscctrl1 = {pm->oscctrl1};\r
208   // Modify\r
209   u_avr32_pm_oscctrl1.OSCCTRL1.mode = mode;\r
210   // Write\r
211   pm->oscctrl1 = u_avr32_pm_oscctrl1.oscctrl1;\r
212 }\r
213 \r
214 \r
215 void pm_enable_osc1_ext_clock(volatile avr32_pm_t *pm)\r
216 {\r
217   pm_set_osc1_mode(pm, AVR32_PM_OSCCTRL1_MODE_EXT_CLOCK);\r
218 }\r
219 \r
220 \r
221 void pm_enable_osc1_crystal(volatile avr32_pm_t *pm, unsigned int fosc1)\r
222 {\r
223   pm_set_osc1_mode(pm, (fosc1 < 8000000) ? AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G2 :\r
224                                            AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G3);\r
225 }\r
226 \r
227 \r
228 void pm_enable_clk1(volatile avr32_pm_t *pm, unsigned int startup)\r
229 {\r
230   pm_enable_clk1_no_wait(pm, startup);\r
231   pm_wait_for_clk1_ready(pm);\r
232 }\r
233 \r
234 \r
235 void pm_disable_clk1(volatile avr32_pm_t *pm)\r
236 {\r
237   pm->mcctrl &= ~AVR32_PM_MCCTRL_OSC1EN_MASK;\r
238 }\r
239 \r
240 \r
241 void pm_enable_clk1_no_wait(volatile avr32_pm_t *pm, unsigned int startup)\r
242 {\r
243   // Read register\r
244   u_avr32_pm_oscctrl1_t u_avr32_pm_oscctrl1 = {pm->oscctrl1};\r
245   // Modify\r
246   u_avr32_pm_oscctrl1.OSCCTRL1.startup = startup;\r
247   // Write back\r
248   pm->oscctrl1 = u_avr32_pm_oscctrl1.oscctrl1;\r
249 \r
250   pm->mcctrl |= AVR32_PM_MCCTRL_OSC1EN_MASK;\r
251 }\r
252 \r
253 \r
254 void pm_wait_for_clk1_ready(volatile avr32_pm_t *pm)\r
255 {\r
256   while (!(pm->poscsr & AVR32_PM_POSCSR_OSC1RDY_MASK));\r
257 }\r
258 \r
259 \r
260 /*! \brief Sets the mode of the 32-kHz oscillator.\r
261  *\r
262  * \param pm Base address of the Power Manager (i.e. &AVR32_PM).\r
263  * \param mode 32-kHz oscillator mode (i.e. AVR32_PM_OSCCTRL32_MODE_x).\r
264  */\r
265 static void pm_set_osc32_mode(volatile avr32_pm_t *pm, unsigned int mode)\r
266 {\r
267   // Read\r
268   u_avr32_pm_oscctrl32_t u_avr32_pm_oscctrl32 = {pm->oscctrl32};\r
269   // Modify\r
270   u_avr32_pm_oscctrl32.OSCCTRL32.mode = mode;\r
271   // Write\r
272   pm->oscctrl32 = u_avr32_pm_oscctrl32.oscctrl32;\r
273 }\r
274 \r
275 \r
276 void pm_enable_osc32_ext_clock(volatile avr32_pm_t *pm)\r
277 {\r
278   pm_set_osc32_mode(pm, AVR32_PM_OSCCTRL32_MODE_EXT_CLOCK);\r
279 }\r
280 \r
281 \r
282 void pm_enable_osc32_crystal(volatile avr32_pm_t *pm)\r
283 {\r
284   pm_set_osc32_mode(pm, AVR32_PM_OSCCTRL32_MODE_CRYSTAL);\r
285 }\r
286 \r
287 \r
288 void pm_enable_clk32(volatile avr32_pm_t *pm, unsigned int startup)\r
289 {\r
290   pm_enable_clk32_no_wait(pm, startup);\r
291   pm_wait_for_clk32_ready(pm);\r
292 }\r
293 \r
294 \r
295 void pm_disable_clk32(volatile avr32_pm_t *pm)\r
296 {\r
297   pm->oscctrl32 &= ~AVR32_PM_OSCCTRL32_OSC32EN_MASK;\r
298 }\r
299 \r
300 \r
301 void pm_enable_clk32_no_wait(volatile avr32_pm_t *pm, unsigned int startup)\r
302 {\r
303   // Read register\r
304   u_avr32_pm_oscctrl32_t u_avr32_pm_oscctrl32 = {pm->oscctrl32};\r
305   // Modify\r
306   u_avr32_pm_oscctrl32.OSCCTRL32.osc32en = 1;\r
307   u_avr32_pm_oscctrl32.OSCCTRL32.startup = startup;\r
308   // Write back\r
309   pm->oscctrl32 = u_avr32_pm_oscctrl32.oscctrl32;\r
310 }\r
311 \r
312 \r
313 void pm_wait_for_clk32_ready(volatile avr32_pm_t *pm)\r
314 {\r
315   while (!(pm->poscsr & AVR32_PM_POSCSR_OSC32RDY_MASK));\r
316 }\r
317 \r
318 \r
319 void pm_cksel(volatile avr32_pm_t *pm,\r
320               unsigned int pbadiv,\r
321               unsigned int pbasel,\r
322               unsigned int pbbdiv,\r
323               unsigned int pbbsel,\r
324               unsigned int hsbdiv,\r
325               unsigned int hsbsel)\r
326 {\r
327   u_avr32_pm_cksel_t u_avr32_pm_cksel = {0};\r
328 \r
329   u_avr32_pm_cksel.CKSEL.cpusel = hsbsel;\r
330   u_avr32_pm_cksel.CKSEL.cpudiv = hsbdiv;\r
331   u_avr32_pm_cksel.CKSEL.hsbsel = hsbsel;\r
332   u_avr32_pm_cksel.CKSEL.hsbdiv = hsbdiv;\r
333   u_avr32_pm_cksel.CKSEL.pbasel = pbasel;\r
334   u_avr32_pm_cksel.CKSEL.pbadiv = pbadiv;\r
335   u_avr32_pm_cksel.CKSEL.pbbsel = pbbsel;\r
336   u_avr32_pm_cksel.CKSEL.pbbdiv = pbbdiv;\r
337 \r
338   pm->cksel = u_avr32_pm_cksel.cksel;\r
339 \r
340   // Wait for ckrdy bit and then clear it\r
341   while (!(pm->poscsr & AVR32_PM_POSCSR_CKRDY_MASK));\r
342 }\r
343 \r
344 \r
345 void pm_gc_setup(volatile avr32_pm_t *pm,\r
346                   unsigned int gc,\r
347                   unsigned int osc_or_pll, // Use Osc (=0) or PLL (=1)\r
348                   unsigned int pll_osc, // Sel Osc0/PLL0 or Osc1/PLL1\r
349                   unsigned int diven,\r
350                   unsigned int div)\r
351 {\r
352   u_avr32_pm_gcctrl_t u_avr32_pm_gcctrl = {0};\r
353 \r
354   u_avr32_pm_gcctrl.GCCTRL.oscsel = pll_osc;\r
355   u_avr32_pm_gcctrl.GCCTRL.pllsel = osc_or_pll;\r
356   u_avr32_pm_gcctrl.GCCTRL.diven  = diven;\r
357   u_avr32_pm_gcctrl.GCCTRL.div    = div;\r
358 \r
359   pm->gcctrl[gc] = u_avr32_pm_gcctrl.gcctrl;\r
360 }\r
361 \r
362 \r
363 void pm_gc_enable(volatile avr32_pm_t *pm,\r
364                   unsigned int gc)\r
365 {\r
366   pm->gcctrl[gc] |= AVR32_PM_GCCTRL_CEN_MASK;\r
367 }\r
368 \r
369 \r
370 void pm_gc_disable(volatile avr32_pm_t *pm,\r
371                    unsigned int gc)\r
372 {\r
373   pm->gcctrl[gc] &= ~AVR32_PM_GCCTRL_CEN_MASK;\r
374 }\r
375 \r
376 \r
377 void pm_pll_setup(volatile avr32_pm_t *pm,\r
378                   unsigned int pll,\r
379                   unsigned int mul,\r
380                   unsigned int div,\r
381                   unsigned int osc,\r
382                   unsigned int lockcount)\r
383 {\r
384   u_avr32_pm_pll_t u_avr32_pm_pll = {0};\r
385 \r
386   u_avr32_pm_pll.PLL.pllosc   = osc;\r
387   u_avr32_pm_pll.PLL.plldiv   = div;\r
388   u_avr32_pm_pll.PLL.pllmul   = mul;\r
389   u_avr32_pm_pll.PLL.pllcount = lockcount;\r
390 \r
391   pm->pll[pll] = u_avr32_pm_pll.pll;\r
392 }\r
393 \r
394 \r
395 void pm_pll_set_option(volatile avr32_pm_t *pm,\r
396                        unsigned int pll,\r
397                        unsigned int pll_freq,\r
398                        unsigned int pll_div2,\r
399                        unsigned int pll_wbwdisable)\r
400 {\r
401   u_avr32_pm_pll_t u_avr32_pm_pll = {pm->pll[pll]};\r
402   u_avr32_pm_pll.PLL.pllopt = pll_freq | (pll_div2 << 1) | (pll_wbwdisable << 2);\r
403   pm->pll[pll] = u_avr32_pm_pll.pll;\r
404 }\r
405 \r
406 \r
407 unsigned int pm_pll_get_option(volatile avr32_pm_t *pm,\r
408                                unsigned int pll)\r
409 {\r
410   return (pm->pll[pll] & AVR32_PM_PLLOPT_MASK) >> AVR32_PM_PLLOPT_OFFSET;\r
411 }\r
412 \r
413 \r
414 void pm_pll_enable(volatile avr32_pm_t *pm,\r
415                   unsigned int pll)\r
416 {\r
417   pm->pll[pll] |= AVR32_PM_PLLEN_MASK;\r
418 }\r
419 \r
420 \r
421 void pm_pll_disable(volatile avr32_pm_t *pm,\r
422                   unsigned int pll)\r
423 {\r
424   pm->pll[pll] &= ~AVR32_PM_PLLEN_MASK;\r
425 }\r
426 \r
427 \r
428 void pm_wait_for_pll0_locked(volatile avr32_pm_t *pm)\r
429 {\r
430   while (!(pm->poscsr & AVR32_PM_POSCSR_LOCK0_MASK));\r
431 \r
432   // Bypass the lock signal of the PLL\r
433   pm->pll[0] |= AVR32_PM_PLL0_PLLBPL_MASK;\r
434 }\r
435 \r
436 \r
437 void pm_wait_for_pll1_locked(volatile avr32_pm_t *pm)\r
438 {\r
439   while (!(pm->poscsr & AVR32_PM_POSCSR_LOCK1_MASK));\r
440 \r
441   // Bypass the lock signal of the PLL\r
442   pm->pll[1] |= AVR32_PM_PLL1_PLLBPL_MASK;\r
443 }\r
444 \r
445 \r
446 void pm_switch_to_clock(volatile avr32_pm_t *pm, unsigned long clock)\r
447 {\r
448   // Read\r
449   u_avr32_pm_mcctrl_t u_avr32_pm_mcctrl = {pm->mcctrl};\r
450   // Modify\r
451   u_avr32_pm_mcctrl.MCCTRL.mcsel = clock;\r
452   // Write back\r
453   pm->mcctrl = u_avr32_pm_mcctrl.mcctrl;\r
454 }\r
455 \r
456 \r
457 void pm_switch_to_osc0(volatile avr32_pm_t *pm, unsigned int fosc0, unsigned int startup)\r
458 {\r
459   pm_enable_osc0_crystal(pm, fosc0);            // Enable the Osc0 in crystal mode\r
460   pm_enable_clk0(pm, startup);                  // Crystal startup time - This parameter is critical and depends on the characteristics of the crystal\r
461   pm_switch_to_clock(pm, AVR32_PM_MCSEL_OSC0);  // Then switch main clock to Osc0\r
462 }\r
463 \r
464 \r
465 void pm_bod_enable_irq(volatile avr32_pm_t *pm)\r
466 {\r
467   pm->ier = AVR32_PM_IER_BODDET_MASK;\r
468 }\r
469 \r
470 \r
471 void pm_bod_disable_irq(volatile avr32_pm_t *pm)\r
472 {\r
473   pm->idr = AVR32_PM_IDR_BODDET_MASK;\r
474 }\r
475 \r
476 \r
477 void pm_bod_clear_irq(volatile avr32_pm_t *pm)\r
478 {\r
479   pm->icr = AVR32_PM_ICR_BODDET_MASK;\r
480 }\r
481 \r
482 \r
483 unsigned long pm_bod_get_irq_status(volatile avr32_pm_t *pm)\r
484 {\r
485   return ((pm->isr & AVR32_PM_ISR_BODDET_MASK) != 0);\r
486 }\r
487 \r
488 \r
489 unsigned long pm_bod_get_irq_enable_bit(volatile avr32_pm_t *pm)\r
490 {\r
491   return ((pm->imr & AVR32_PM_IMR_BODDET_MASK) != 0);\r
492 }\r
493 \r
494 \r
495 unsigned long pm_bod_get_level(volatile avr32_pm_t *pm)\r
496 {\r
497   return (pm->bod & AVR32_PM_BOD_LEVEL_MASK) >> AVR32_PM_BOD_LEVEL_OFFSET;\r
498 }\r
499 \r
500 \r
501 void pm_write_gplp(volatile avr32_pm_t *pm,unsigned long gplp, unsigned long value)\r
502 {\r
503   pm->gplp[gplp] = value;\r
504 }\r
505 \r
506 \r
507 unsigned long pm_read_gplp(volatile avr32_pm_t *pm,unsigned long gplp)\r
508 {\r
509   return pm->gplp[gplp];\r
510 }\r