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 driver.
\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
49 #include "compiler.h"
\r
53 /*! \name PM Writable Bit-Field Registers
\r
59 unsigned long mcctrl;
\r
60 avr32_pm_mcctrl_t MCCTRL;
\r
61 } u_avr32_pm_mcctrl_t;
\r
65 unsigned long cksel;
\r
66 avr32_pm_cksel_t CKSEL;
\r
67 } u_avr32_pm_cksel_t;
\r
77 unsigned long oscctrl0;
\r
78 avr32_pm_oscctrl0_t OSCCTRL0;
\r
79 } u_avr32_pm_oscctrl0_t;
\r
83 unsigned long oscctrl1;
\r
84 avr32_pm_oscctrl1_t OSCCTRL1;
\r
85 } u_avr32_pm_oscctrl1_t;
\r
89 unsigned long oscctrl32;
\r
90 avr32_pm_oscctrl32_t OSCCTRL32;
\r
91 } u_avr32_pm_oscctrl32_t;
\r
102 avr32_pm_idr_t IDR;
\r
103 } u_avr32_pm_idr_t;
\r
108 avr32_pm_icr_t ICR;
\r
109 } u_avr32_pm_icr_t;
\r
113 unsigned long gcctrl;
\r
114 avr32_pm_gcctrl_t GCCTRL;
\r
115 } u_avr32_pm_gcctrl_t;
\r
119 unsigned long rccr;
\r
120 avr32_pm_rccr_t RCCR;
\r
121 } u_avr32_pm_rccr_t;
\r
125 unsigned long bgcr;
\r
126 avr32_pm_bgcr_t BGCR;
\r
127 } u_avr32_pm_bgcr_t;
\r
131 unsigned long vregcr;
\r
132 avr32_pm_vregcr_t VREGCR;
\r
133 } u_avr32_pm_vregcr_t;
\r
138 avr32_pm_bod_t BOD;
\r
139 } u_avr32_pm_bod_t;
\r
144 /*! \brief Sets the mode of the oscillator 0.
\r
146 * \param pm Base address of the Power Manager (i.e. &AVR32_PM).
\r
147 * \param mode Oscillator 0 mode (i.e. AVR32_PM_OSCCTRL0_MODE_x).
\r
149 static void pm_set_osc0_mode(volatile avr32_pm_t *pm, unsigned int mode)
\r
152 u_avr32_pm_oscctrl0_t u_avr32_pm_oscctrl0 = {pm->oscctrl0};
\r
154 u_avr32_pm_oscctrl0.OSCCTRL0.mode = mode;
\r
156 pm->oscctrl0 = u_avr32_pm_oscctrl0.oscctrl0;
\r
160 void pm_enable_osc0_ext_clock(volatile avr32_pm_t *pm)
\r
162 pm_set_osc0_mode(pm, AVR32_PM_OSCCTRL0_MODE_EXT_CLOCK);
\r
166 void pm_enable_osc0_crystal(volatile avr32_pm_t *pm, unsigned int fosc0)
\r
168 pm_set_osc0_mode(pm, (fosc0 < 900000) ? AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G0 :
\r
169 (fosc0 < 3000000) ? AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G1 :
\r
170 (fosc0 < 8000000) ? AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G2 :
\r
171 AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G3);
\r
175 void pm_enable_clk0(volatile avr32_pm_t *pm, unsigned int startup)
\r
177 pm_enable_clk0_no_wait(pm, startup);
\r
178 pm_wait_for_clk0_ready(pm);
\r
182 void pm_disable_clk0(volatile avr32_pm_t *pm)
\r
184 pm->mcctrl &= ~AVR32_PM_MCCTRL_OSC0EN_MASK;
\r
188 void pm_enable_clk0_no_wait(volatile avr32_pm_t *pm, unsigned int startup)
\r
191 u_avr32_pm_oscctrl0_t u_avr32_pm_oscctrl0 = {pm->oscctrl0};
\r
193 u_avr32_pm_oscctrl0.OSCCTRL0.startup = startup;
\r
195 pm->oscctrl0 = u_avr32_pm_oscctrl0.oscctrl0;
\r
197 pm->mcctrl |= AVR32_PM_MCCTRL_OSC0EN_MASK;
\r
201 void pm_wait_for_clk0_ready(volatile avr32_pm_t *pm)
\r
203 while (!(pm->poscsr & AVR32_PM_POSCSR_OSC0RDY_MASK));
\r
207 /*! \brief Sets the mode of the oscillator 1.
\r
209 * \param pm Base address of the Power Manager (i.e. &AVR32_PM).
\r
210 * \param mode Oscillator 1 mode (i.e. AVR32_PM_OSCCTRL1_MODE_x).
\r
212 static void pm_set_osc1_mode(volatile avr32_pm_t *pm, unsigned int mode)
\r
215 u_avr32_pm_oscctrl1_t u_avr32_pm_oscctrl1 = {pm->oscctrl1};
\r
217 u_avr32_pm_oscctrl1.OSCCTRL1.mode = mode;
\r
219 pm->oscctrl1 = u_avr32_pm_oscctrl1.oscctrl1;
\r
223 void pm_enable_osc1_ext_clock(volatile avr32_pm_t *pm)
\r
225 pm_set_osc1_mode(pm, AVR32_PM_OSCCTRL1_MODE_EXT_CLOCK);
\r
229 void pm_enable_osc1_crystal(volatile avr32_pm_t *pm, unsigned int fosc1)
\r
231 pm_set_osc1_mode(pm, (fosc1 < 900000) ? AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G0 :
\r
232 (fosc1 < 3000000) ? AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G1 :
\r
233 (fosc1 < 8000000) ? AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G2 :
\r
234 AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G3);
\r
238 void pm_enable_clk1(volatile avr32_pm_t *pm, unsigned int startup)
\r
240 pm_enable_clk1_no_wait(pm, startup);
\r
241 pm_wait_for_clk1_ready(pm);
\r
245 void pm_disable_clk1(volatile avr32_pm_t *pm)
\r
247 pm->mcctrl &= ~AVR32_PM_MCCTRL_OSC1EN_MASK;
\r
251 void pm_enable_clk1_no_wait(volatile avr32_pm_t *pm, unsigned int startup)
\r
254 u_avr32_pm_oscctrl1_t u_avr32_pm_oscctrl1 = {pm->oscctrl1};
\r
256 u_avr32_pm_oscctrl1.OSCCTRL1.startup = startup;
\r
258 pm->oscctrl1 = u_avr32_pm_oscctrl1.oscctrl1;
\r
260 pm->mcctrl |= AVR32_PM_MCCTRL_OSC1EN_MASK;
\r
264 void pm_wait_for_clk1_ready(volatile avr32_pm_t *pm)
\r
266 while (!(pm->poscsr & AVR32_PM_POSCSR_OSC1RDY_MASK));
\r
270 /*! \brief Sets the mode of the 32-kHz oscillator.
\r
272 * \param pm Base address of the Power Manager (i.e. &AVR32_PM).
\r
273 * \param mode 32-kHz oscillator mode (i.e. AVR32_PM_OSCCTRL32_MODE_x).
\r
275 static void pm_set_osc32_mode(volatile avr32_pm_t *pm, unsigned int mode)
\r
278 u_avr32_pm_oscctrl32_t u_avr32_pm_oscctrl32 = {pm->oscctrl32};
\r
280 u_avr32_pm_oscctrl32.OSCCTRL32.mode = mode;
\r
282 pm->oscctrl32 = u_avr32_pm_oscctrl32.oscctrl32;
\r
286 void pm_enable_osc32_ext_clock(volatile avr32_pm_t *pm)
\r
288 pm_set_osc32_mode(pm, AVR32_PM_OSCCTRL32_MODE_EXT_CLOCK);
\r
292 void pm_enable_osc32_crystal(volatile avr32_pm_t *pm)
\r
294 pm_set_osc32_mode(pm, AVR32_PM_OSCCTRL32_MODE_CRYSTAL);
\r
298 void pm_enable_clk32(volatile avr32_pm_t *pm, unsigned int startup)
\r
300 pm_enable_clk32_no_wait(pm, startup);
\r
301 pm_wait_for_clk32_ready(pm);
\r
305 void pm_disable_clk32(volatile avr32_pm_t *pm)
\r
307 pm->oscctrl32 &= ~AVR32_PM_OSCCTRL32_OSC32EN_MASK;
\r
311 void pm_enable_clk32_no_wait(volatile avr32_pm_t *pm, unsigned int startup)
\r
314 u_avr32_pm_oscctrl32_t u_avr32_pm_oscctrl32 = {pm->oscctrl32};
\r
316 u_avr32_pm_oscctrl32.OSCCTRL32.osc32en = 1;
\r
317 u_avr32_pm_oscctrl32.OSCCTRL32.startup = startup;
\r
319 pm->oscctrl32 = u_avr32_pm_oscctrl32.oscctrl32;
\r
323 void pm_wait_for_clk32_ready(volatile avr32_pm_t *pm)
\r
325 while (!(pm->poscsr & AVR32_PM_POSCSR_OSC32RDY_MASK));
\r
329 void pm_cksel(volatile avr32_pm_t *pm,
\r
330 unsigned int pbadiv,
\r
331 unsigned int pbasel,
\r
332 unsigned int pbbdiv,
\r
333 unsigned int pbbsel,
\r
334 unsigned int hsbdiv,
\r
335 unsigned int hsbsel)
\r
337 u_avr32_pm_cksel_t u_avr32_pm_cksel = {0};
\r
339 u_avr32_pm_cksel.CKSEL.cpusel = hsbsel;
\r
340 u_avr32_pm_cksel.CKSEL.cpudiv = hsbdiv;
\r
341 u_avr32_pm_cksel.CKSEL.hsbsel = hsbsel;
\r
342 u_avr32_pm_cksel.CKSEL.hsbdiv = hsbdiv;
\r
343 u_avr32_pm_cksel.CKSEL.pbasel = pbasel;
\r
344 u_avr32_pm_cksel.CKSEL.pbadiv = pbadiv;
\r
345 u_avr32_pm_cksel.CKSEL.pbbsel = pbbsel;
\r
346 u_avr32_pm_cksel.CKSEL.pbbdiv = pbbdiv;
\r
348 pm->cksel = u_avr32_pm_cksel.cksel;
\r
350 // Wait for ckrdy bit and then clear it
\r
351 while (!(pm->poscsr & AVR32_PM_POSCSR_CKRDY_MASK));
\r
355 void pm_gc_setup(volatile avr32_pm_t *pm,
\r
357 unsigned int osc_or_pll, // Use Osc (=0) or PLL (=1)
\r
358 unsigned int pll_osc, // Sel Osc0/PLL0 or Osc1/PLL1
\r
359 unsigned int diven,
\r
362 u_avr32_pm_gcctrl_t u_avr32_pm_gcctrl = {0};
\r
364 u_avr32_pm_gcctrl.GCCTRL.oscsel = pll_osc;
\r
365 u_avr32_pm_gcctrl.GCCTRL.pllsel = osc_or_pll;
\r
366 u_avr32_pm_gcctrl.GCCTRL.diven = diven;
\r
367 u_avr32_pm_gcctrl.GCCTRL.div = div;
\r
369 pm->gcctrl[gc] = u_avr32_pm_gcctrl.gcctrl;
\r
373 void pm_gc_enable(volatile avr32_pm_t *pm,
\r
376 pm->gcctrl[gc] |= AVR32_PM_GCCTRL_CEN_MASK;
\r
380 void pm_gc_disable(volatile avr32_pm_t *pm,
\r
383 pm->gcctrl[gc] &= ~AVR32_PM_GCCTRL_CEN_MASK;
\r
387 void pm_pll_setup(volatile avr32_pm_t *pm,
\r
392 unsigned int lockcount)
\r
394 u_avr32_pm_pll_t u_avr32_pm_pll = {0};
\r
396 u_avr32_pm_pll.PLL.pllosc = osc;
\r
397 u_avr32_pm_pll.PLL.plldiv = div;
\r
398 u_avr32_pm_pll.PLL.pllmul = mul;
\r
399 u_avr32_pm_pll.PLL.pllcount = lockcount;
\r
401 pm->pll[pll] = u_avr32_pm_pll.pll;
\r
405 void pm_pll_set_option(volatile avr32_pm_t *pm,
\r
407 unsigned int pll_freq,
\r
408 unsigned int pll_div2,
\r
409 unsigned int pll_wbwdisable)
\r
411 u_avr32_pm_pll_t u_avr32_pm_pll = {pm->pll[pll]};
\r
412 u_avr32_pm_pll.PLL.pllopt = pll_freq | (pll_div2 << 1) | (pll_wbwdisable << 2);
\r
413 pm->pll[pll] = u_avr32_pm_pll.pll;
\r
417 unsigned int pm_pll_get_option(volatile avr32_pm_t *pm,
\r
420 return (pm->pll[pll] & AVR32_PM_PLLOPT_MASK) >> AVR32_PM_PLLOPT_OFFSET;
\r
424 void pm_pll_enable(volatile avr32_pm_t *pm,
\r
427 pm->pll[pll] |= AVR32_PM_PLLEN_MASK;
\r
431 void pm_pll_disable(volatile avr32_pm_t *pm,
\r
434 pm->pll[pll] &= ~AVR32_PM_PLLEN_MASK;
\r
438 void pm_wait_for_pll0_locked(volatile avr32_pm_t *pm)
\r
440 while (!(pm->poscsr & AVR32_PM_POSCSR_LOCK0_MASK));
\r
444 void pm_wait_for_pll1_locked(volatile avr32_pm_t *pm)
\r
446 while (!(pm->poscsr & AVR32_PM_POSCSR_LOCK1_MASK));
\r
450 void pm_switch_to_clock(volatile avr32_pm_t *pm, unsigned long clock)
\r
453 u_avr32_pm_mcctrl_t u_avr32_pm_mcctrl = {pm->mcctrl};
\r
455 u_avr32_pm_mcctrl.MCCTRL.mcsel = clock;
\r
457 pm->mcctrl = u_avr32_pm_mcctrl.mcctrl;
\r
461 void pm_switch_to_osc0(volatile avr32_pm_t *pm, unsigned int fosc0, unsigned int startup)
\r
463 pm_enable_osc0_crystal(pm, fosc0); // Enable the Osc0 in crystal mode
\r
464 pm_enable_clk0(pm, startup); // Crystal startup time - This parameter is critical and depends on the characteristics of the crystal
\r
465 pm_switch_to_clock(pm, AVR32_PM_MCSEL_OSC0); // Then switch main clock to Osc0
\r
469 void pm_bod_enable_irq(volatile avr32_pm_t *pm)
\r
471 pm->ier = AVR32_PM_IER_BODDET_MASK;
\r
475 void pm_bod_disable_irq(volatile avr32_pm_t *pm)
\r
477 Bool global_interrupt_enabled = Is_global_interrupt_enabled();
\r
479 if (global_interrupt_enabled) Disable_global_interrupt();
\r
480 pm->idr = AVR32_PM_IDR_BODDET_MASK;
\r
482 if (global_interrupt_enabled) Enable_global_interrupt();
\r
486 void pm_bod_clear_irq(volatile avr32_pm_t *pm)
\r
488 pm->icr = AVR32_PM_ICR_BODDET_MASK;
\r
492 unsigned long pm_bod_get_irq_status(volatile avr32_pm_t *pm)
\r
494 return ((pm->isr & AVR32_PM_ISR_BODDET_MASK) != 0);
\r
498 unsigned long pm_bod_get_irq_enable_bit(volatile avr32_pm_t *pm)
\r
500 return ((pm->imr & AVR32_PM_IMR_BODDET_MASK) != 0);
\r
504 unsigned long pm_bod_get_level(volatile avr32_pm_t *pm)
\r
506 return (pm->bod & AVR32_PM_BOD_LEVEL_MASK) >> AVR32_PM_BOD_LEVEL_OFFSET;
\r
510 unsigned long pm_read_gplp(volatile avr32_pm_t *pm, unsigned long gplp)
\r
512 return pm->gplp[gplp];
\r
516 void pm_write_gplp(volatile avr32_pm_t *pm, unsigned long gplp, unsigned long value)
\r
518 pm->gplp[gplp] = value;
\r
522 long pm_enable_module(volatile avr32_pm_t *pm, unsigned long module)
\r
524 unsigned long domain = module>>5;
\r
525 unsigned long *regptr = (unsigned long*)(&(pm->cpumask) + domain);
\r
527 // Implementation-specific shortcut: the ckMASK registers are contiguous and
\r
528 // memory-mapped in that order: CPUMASK, HSBMASK, PBAMASK, PBBMASK.
\r
530 *regptr |= (1<<(module%32));
\r
535 long pm_disable_module(volatile avr32_pm_t *pm, unsigned long module)
\r
537 unsigned long domain = module>>5;
\r
538 unsigned long *regptr = (unsigned long*)(&(pm->cpumask) + domain);
\r
540 // Implementation-specific shortcut: the ckMASK registers are contiguous and
\r
541 // memory-mapped in that order: CPUMASK, HSBMASK, PBAMASK, PBBMASK.
\r
543 *regptr &= ~(1<<(module%32));
\r