1 /*****************************************************************************
2  *
3  * \file
4  *
5  * \brief Power Manager driver.
6  *
7  * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
8  *
9  * \asf_license_start
10  *
11  * \page License
12  *
13  * Subject to your compliance with these terms, you may use Microchip
14  * software and any derivatives exclusively with Microchip products.
15  * It is your responsibility to comply with third party license terms applicable
16  * to your use of third party software (including open source software) that
17  * may accompany Microchip software.
18  *
19  * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
20  * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
21  * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
22  * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
23  * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
24  * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
25  * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
26  * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT
27  * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
28  * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
29  * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
30  *
31  * \asf_license_stop
32  *
33  *****************************************************************************/
34 /*
35  * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
36  */
37 
38 
39 #include "compiler.h"
40 #include "pm.h"
41 
42 
43 /*! \name PM Writable Bit-Field Registers
44  */
45 //! @{
46 
47 typedef union
48 {
49   unsigned long                 mcctrl;
50   avr32_pm_mcctrl_t             MCCTRL;
51 } u_avr32_pm_mcctrl_t;
52 
53 typedef union
54 {
55   unsigned long                 cksel;
56   avr32_pm_cksel_t              CKSEL;
57 } u_avr32_pm_cksel_t;
58 
59 typedef union
60 {
61   unsigned long                 pll;
62   avr32_pm_pll_t                PLL;
63 } u_avr32_pm_pll_t;
64 
65 typedef union
66 {
67   unsigned long                 oscctrl0;
68   avr32_pm_oscctrl0_t           OSCCTRL0;
69 } u_avr32_pm_oscctrl0_t;
70 
71 typedef union
72 {
73   unsigned long                 oscctrl1;
74   avr32_pm_oscctrl1_t           OSCCTRL1;
75 } u_avr32_pm_oscctrl1_t;
76 
77 typedef union
78 {
79   unsigned long                 oscctrl32;
80   avr32_pm_oscctrl32_t          OSCCTRL32;
81 } u_avr32_pm_oscctrl32_t;
82 
83 typedef union
84 {
85   unsigned long                 ier;
86   avr32_pm_ier_t                IER;
87 } u_avr32_pm_ier_t;
88 
89 typedef union
90 {
91   unsigned long                 idr;
92   avr32_pm_idr_t                IDR;
93 } u_avr32_pm_idr_t;
94 
95 typedef union
96 {
97   unsigned long                 icr;
98   avr32_pm_icr_t                ICR;
99 } u_avr32_pm_icr_t;
100 
101 typedef union
102 {
103   unsigned long                 gcctrl;
104   avr32_pm_gcctrl_t             GCCTRL;
105 } u_avr32_pm_gcctrl_t;
106 
107 typedef union
108 {
109   unsigned long                 rccr;
110   avr32_pm_rccr_t               RCCR;
111 } u_avr32_pm_rccr_t;
112 
113 typedef union
114 {
115   unsigned long                 bgcr;
116   avr32_pm_bgcr_t               BGCR;
117 } u_avr32_pm_bgcr_t;
118 
119 typedef union
120 {
121   unsigned long                 vregcr;
122   avr32_pm_vregcr_t             VREGCR;
123 } u_avr32_pm_vregcr_t;
124 
125 typedef union
126 {
127   unsigned long                 bod;
128   avr32_pm_bod_t                BOD;
129 } u_avr32_pm_bod_t;
130 
131 //! @}
132 
133 
134 /*! \brief Sets the mode of the oscillator 0.
135  *
136  * \param pm Base address of the Power Manager (i.e. &AVR32_PM).
137  * \param mode Oscillator 0 mode (i.e. AVR32_PM_OSCCTRL0_MODE_x).
138  */
pm_set_osc0_mode(volatile avr32_pm_t * pm,unsigned int mode)139 static void pm_set_osc0_mode(volatile avr32_pm_t *pm, unsigned int mode)
140 {
141   // Read
142   u_avr32_pm_oscctrl0_t u_avr32_pm_oscctrl0 = {pm->oscctrl0};
143   // Modify
144   u_avr32_pm_oscctrl0.OSCCTRL0.mode = mode;
145   // Write
146   pm->oscctrl0 = u_avr32_pm_oscctrl0.oscctrl0;
147 }
148 
149 
pm_enable_osc0_ext_clock(volatile avr32_pm_t * pm)150 void pm_enable_osc0_ext_clock(volatile avr32_pm_t *pm)
151 {
152   pm_set_osc0_mode(pm, AVR32_PM_OSCCTRL0_MODE_EXT_CLOCK);
153 }
154 
155 
pm_enable_osc0_crystal(volatile avr32_pm_t * pm,unsigned int fosc0)156 void pm_enable_osc0_crystal(volatile avr32_pm_t *pm, unsigned int fosc0)
157 {
158   pm_set_osc0_mode(pm, (fosc0 <  900000) ? AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G0 :
159                        (fosc0 < 3000000) ? AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G1 :
160                        (fosc0 < 8000000) ? AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G2 :
161                                            AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G3);
162 }
163 
164 
pm_enable_clk0(volatile avr32_pm_t * pm,unsigned int startup)165 void pm_enable_clk0(volatile avr32_pm_t *pm, unsigned int startup)
166 {
167   pm_enable_clk0_no_wait(pm, startup);
168   pm_wait_for_clk0_ready(pm);
169 }
170 
171 
pm_disable_clk0(volatile avr32_pm_t * pm)172 void pm_disable_clk0(volatile avr32_pm_t *pm)
173 {
174   pm->mcctrl &= ~AVR32_PM_MCCTRL_OSC0EN_MASK;
175 }
176 
177 
pm_enable_clk0_no_wait(volatile avr32_pm_t * pm,unsigned int startup)178 void pm_enable_clk0_no_wait(volatile avr32_pm_t *pm, unsigned int startup)
179 {
180   // Read register
181   u_avr32_pm_oscctrl0_t u_avr32_pm_oscctrl0 = {pm->oscctrl0};
182   // Modify
183   u_avr32_pm_oscctrl0.OSCCTRL0.startup = startup;
184   // Write back
185   pm->oscctrl0 = u_avr32_pm_oscctrl0.oscctrl0;
186 
187   pm->mcctrl |= AVR32_PM_MCCTRL_OSC0EN_MASK;
188 }
189 
190 
pm_wait_for_clk0_ready(volatile avr32_pm_t * pm)191 void pm_wait_for_clk0_ready(volatile avr32_pm_t *pm)
192 {
193   while (!(pm->poscsr & AVR32_PM_POSCSR_OSC0RDY_MASK));
194 }
195 
196 
197 /*! \brief Sets the mode of the oscillator 1.
198  *
199  * \param pm Base address of the Power Manager (i.e. &AVR32_PM).
200  * \param mode Oscillator 1 mode (i.e. AVR32_PM_OSCCTRL1_MODE_x).
201  */
pm_set_osc1_mode(volatile avr32_pm_t * pm,unsigned int mode)202 static void pm_set_osc1_mode(volatile avr32_pm_t *pm, unsigned int mode)
203 {
204   // Read
205   u_avr32_pm_oscctrl1_t u_avr32_pm_oscctrl1 = {pm->oscctrl1};
206   // Modify
207   u_avr32_pm_oscctrl1.OSCCTRL1.mode = mode;
208   // Write
209   pm->oscctrl1 = u_avr32_pm_oscctrl1.oscctrl1;
210 }
211 
212 
pm_enable_osc1_ext_clock(volatile avr32_pm_t * pm)213 void pm_enable_osc1_ext_clock(volatile avr32_pm_t *pm)
214 {
215   pm_set_osc1_mode(pm, AVR32_PM_OSCCTRL1_MODE_EXT_CLOCK);
216 }
217 
218 
pm_enable_osc1_crystal(volatile avr32_pm_t * pm,unsigned int fosc1)219 void pm_enable_osc1_crystal(volatile avr32_pm_t *pm, unsigned int fosc1)
220 {
221   pm_set_osc1_mode(pm, (fosc1 <  900000) ? AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G0 :
222                        (fosc1 < 3000000) ? AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G1 :
223                        (fosc1 < 8000000) ? AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G2 :
224                                            AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G3);
225 }
226 
227 
pm_enable_clk1(volatile avr32_pm_t * pm,unsigned int startup)228 void pm_enable_clk1(volatile avr32_pm_t *pm, unsigned int startup)
229 {
230   pm_enable_clk1_no_wait(pm, startup);
231   pm_wait_for_clk1_ready(pm);
232 }
233 
234 
pm_disable_clk1(volatile avr32_pm_t * pm)235 void pm_disable_clk1(volatile avr32_pm_t *pm)
236 {
237   pm->mcctrl &= ~AVR32_PM_MCCTRL_OSC1EN_MASK;
238 }
239 
240 
pm_enable_clk1_no_wait(volatile avr32_pm_t * pm,unsigned int startup)241 void pm_enable_clk1_no_wait(volatile avr32_pm_t *pm, unsigned int startup)
242 {
243   // Read register
244   u_avr32_pm_oscctrl1_t u_avr32_pm_oscctrl1 = {pm->oscctrl1};
245   // Modify
246   u_avr32_pm_oscctrl1.OSCCTRL1.startup = startup;
247   // Write back
248   pm->oscctrl1 = u_avr32_pm_oscctrl1.oscctrl1;
249 
250   pm->mcctrl |= AVR32_PM_MCCTRL_OSC1EN_MASK;
251 }
252 
253 
pm_wait_for_clk1_ready(volatile avr32_pm_t * pm)254 void pm_wait_for_clk1_ready(volatile avr32_pm_t *pm)
255 {
256   while (!(pm->poscsr & AVR32_PM_POSCSR_OSC1RDY_MASK));
257 }
258 
259 
260 /*! \brief Sets the mode of the 32-kHz oscillator.
261  *
262  * \param pm Base address of the Power Manager (i.e. &AVR32_PM).
263  * \param mode 32-kHz oscillator mode (i.e. AVR32_PM_OSCCTRL32_MODE_x).
264  */
pm_set_osc32_mode(volatile avr32_pm_t * pm,unsigned int mode)265 static void pm_set_osc32_mode(volatile avr32_pm_t *pm, unsigned int mode)
266 {
267   // Read
268   u_avr32_pm_oscctrl32_t u_avr32_pm_oscctrl32 = {pm->oscctrl32};
269   // Modify
270   u_avr32_pm_oscctrl32.OSCCTRL32.mode = mode;
271   // Write
272   pm->oscctrl32 = u_avr32_pm_oscctrl32.oscctrl32;
273 }
274 
275 
pm_enable_osc32_ext_clock(volatile avr32_pm_t * pm)276 void pm_enable_osc32_ext_clock(volatile avr32_pm_t *pm)
277 {
278   pm_set_osc32_mode(pm, AVR32_PM_OSCCTRL32_MODE_EXT_CLOCK);
279 }
280 
281 
pm_enable_osc32_crystal(volatile avr32_pm_t * pm)282 void pm_enable_osc32_crystal(volatile avr32_pm_t *pm)
283 {
284   pm_set_osc32_mode(pm, AVR32_PM_OSCCTRL32_MODE_CRYSTAL);
285 }
286 
287 
pm_enable_clk32(volatile avr32_pm_t * pm,unsigned int startup)288 void pm_enable_clk32(volatile avr32_pm_t *pm, unsigned int startup)
289 {
290   pm_enable_clk32_no_wait(pm, startup);
291   pm_wait_for_clk32_ready(pm);
292 }
293 
294 
pm_disable_clk32(volatile avr32_pm_t * pm)295 void pm_disable_clk32(volatile avr32_pm_t *pm)
296 {
297   pm->oscctrl32 &= ~AVR32_PM_OSCCTRL32_OSC32EN_MASK;
298 }
299 
300 
pm_enable_clk32_no_wait(volatile avr32_pm_t * pm,unsigned int startup)301 void pm_enable_clk32_no_wait(volatile avr32_pm_t *pm, unsigned int startup)
302 {
303   // Read register
304   u_avr32_pm_oscctrl32_t u_avr32_pm_oscctrl32 = {pm->oscctrl32};
305   // Modify
306   u_avr32_pm_oscctrl32.OSCCTRL32.osc32en = 1;
307   u_avr32_pm_oscctrl32.OSCCTRL32.startup = startup;
308   // Write back
309   pm->oscctrl32 = u_avr32_pm_oscctrl32.oscctrl32;
310 }
311 
312 
pm_wait_for_clk32_ready(volatile avr32_pm_t * pm)313 void pm_wait_for_clk32_ready(volatile avr32_pm_t *pm)
314 {
315   while (!(pm->poscsr & AVR32_PM_POSCSR_OSC32RDY_MASK));
316 }
317 
318 
pm_cksel_get(volatile avr32_pm_t * pm,unsigned long * p_cksel)319 void pm_cksel_get(volatile avr32_pm_t *pm, unsigned long *p_cksel)
320 {
321   *p_cksel = pm->cksel;
322 }
323 
324 
pm_cksel_set(volatile avr32_pm_t * pm,unsigned long cksel)325 void pm_cksel_set(volatile avr32_pm_t *pm, unsigned long cksel)
326 {
327   pm->cksel = cksel;
328 
329   // Wait for ckrdy bit and then clear it
330   while (!(pm->poscsr & AVR32_PM_POSCSR_CKRDY_MASK));
331 }
332 
333 
pm_cksel(volatile avr32_pm_t * pm,unsigned int pbadiv,unsigned int pbasel,unsigned int pbbdiv,unsigned int pbbsel,unsigned int hsbdiv,unsigned int hsbsel)334 void pm_cksel(volatile avr32_pm_t *pm,
335               unsigned int pbadiv,
336               unsigned int pbasel,
337               unsigned int pbbdiv,
338               unsigned int pbbsel,
339               unsigned int hsbdiv,
340               unsigned int hsbsel)
341 {
342   u_avr32_pm_cksel_t u_avr32_pm_cksel = {0};
343 
344   u_avr32_pm_cksel.CKSEL.cpusel = hsbsel;
345   u_avr32_pm_cksel.CKSEL.cpudiv = hsbdiv;
346   u_avr32_pm_cksel.CKSEL.hsbsel = hsbsel;
347   u_avr32_pm_cksel.CKSEL.hsbdiv = hsbdiv;
348   u_avr32_pm_cksel.CKSEL.pbasel = pbasel;
349   u_avr32_pm_cksel.CKSEL.pbadiv = pbadiv;
350   u_avr32_pm_cksel.CKSEL.pbbsel = pbbsel;
351   u_avr32_pm_cksel.CKSEL.pbbdiv = pbbdiv;
352 
353   pm->cksel = u_avr32_pm_cksel.cksel;
354 
355   // Wait for ckrdy bit and then clear it
356   while (!(pm->poscsr & AVR32_PM_POSCSR_CKRDY_MASK));
357 }
358 
359 
pm_gc_setup(volatile avr32_pm_t * pm,unsigned int gc,unsigned int osc_or_pll,unsigned int pll_osc,unsigned int diven,unsigned int div)360 void pm_gc_setup(volatile avr32_pm_t *pm,
361                   unsigned int gc,
362                   unsigned int osc_or_pll, // Use Osc (=0) or PLL (=1)
363                   unsigned int pll_osc, // Sel Osc0/PLL0 or Osc1/PLL1
364                   unsigned int diven,
365                   unsigned int div)
366 {
367   u_avr32_pm_gcctrl_t u_avr32_pm_gcctrl = {0};
368 
369   u_avr32_pm_gcctrl.GCCTRL.oscsel = pll_osc;
370   u_avr32_pm_gcctrl.GCCTRL.pllsel = osc_or_pll;
371   u_avr32_pm_gcctrl.GCCTRL.diven  = diven;
372   u_avr32_pm_gcctrl.GCCTRL.div    = div;
373 
374   pm->gcctrl[gc] = u_avr32_pm_gcctrl.gcctrl;
375 }
376 
377 
pm_gc_enable(volatile avr32_pm_t * pm,unsigned int gc)378 void pm_gc_enable(volatile avr32_pm_t *pm,
379                   unsigned int gc)
380 {
381   pm->gcctrl[gc] |= AVR32_PM_GCCTRL_CEN_MASK;
382 }
383 
384 
pm_gc_disable(volatile avr32_pm_t * pm,unsigned int gc)385 void pm_gc_disable(volatile avr32_pm_t *pm,
386                    unsigned int gc)
387 {
388   pm->gcctrl[gc] &= ~AVR32_PM_GCCTRL_CEN_MASK;
389 }
390 
391 
pm_pll_setup(volatile avr32_pm_t * pm,unsigned int pll,unsigned int mul,unsigned int div,unsigned int osc,unsigned int lockcount)392 void pm_pll_setup(volatile avr32_pm_t *pm,
393                   unsigned int pll,
394                   unsigned int mul,
395                   unsigned int div,
396                   unsigned int osc,
397                   unsigned int lockcount)
398 {
399   u_avr32_pm_pll_t u_avr32_pm_pll = {0};
400 
401   u_avr32_pm_pll.PLL.pllosc   = osc;
402   u_avr32_pm_pll.PLL.plldiv   = div;
403   u_avr32_pm_pll.PLL.pllmul   = mul;
404   u_avr32_pm_pll.PLL.pllcount = lockcount;
405 
406   pm->pll[pll] = u_avr32_pm_pll.pll;
407 }
408 
409 
pm_pll_set_option(volatile avr32_pm_t * pm,unsigned int pll,unsigned int pll_freq,unsigned int pll_div2,unsigned int pll_wbwdisable)410 void pm_pll_set_option(volatile avr32_pm_t *pm,
411                        unsigned int pll,
412                        unsigned int pll_freq,
413                        unsigned int pll_div2,
414                        unsigned int pll_wbwdisable)
415 {
416   u_avr32_pm_pll_t u_avr32_pm_pll = {pm->pll[pll]};
417   u_avr32_pm_pll.PLL.pllopt = pll_freq | (pll_div2 << 1) | (pll_wbwdisable << 2);
418   pm->pll[pll] = u_avr32_pm_pll.pll;
419 }
420 
421 
pm_pll_get_option(volatile avr32_pm_t * pm,unsigned int pll)422 unsigned int pm_pll_get_option(volatile avr32_pm_t *pm,
423                                unsigned int pll)
424 {
425   return (pm->pll[pll] & AVR32_PM_PLLOPT_MASK) >> AVR32_PM_PLLOPT_OFFSET;
426 }
427 
428 
pm_pll_enable(volatile avr32_pm_t * pm,unsigned int pll)429 void pm_pll_enable(volatile avr32_pm_t *pm,
430                   unsigned int pll)
431 {
432   pm->pll[pll] |= AVR32_PM_PLLEN_MASK;
433 }
434 
435 
pm_pll_disable(volatile avr32_pm_t * pm,unsigned int pll)436 void pm_pll_disable(volatile avr32_pm_t *pm,
437                   unsigned int pll)
438 {
439   pm->pll[pll] &= ~AVR32_PM_PLLEN_MASK;
440 }
441 
442 
pm_wait_for_pll0_locked(volatile avr32_pm_t * pm)443 void pm_wait_for_pll0_locked(volatile avr32_pm_t *pm)
444 {
445   while (!(pm->poscsr & AVR32_PM_POSCSR_LOCK0_MASK));
446 }
447 
448 
pm_wait_for_pll1_locked(volatile avr32_pm_t * pm)449 void pm_wait_for_pll1_locked(volatile avr32_pm_t *pm)
450 {
451   while (!(pm->poscsr & AVR32_PM_POSCSR_LOCK1_MASK));
452 }
453 
454 
pm_get_clock(volatile avr32_pm_t * pm)455 unsigned long pm_get_clock(volatile avr32_pm_t *pm)
456 {
457   u_avr32_pm_mcctrl_t u_avr32_pm_mcctrl = {pm->mcctrl};
458   return u_avr32_pm_mcctrl.MCCTRL.mcsel;
459 }
460 
461 
pm_switch_to_clock(volatile avr32_pm_t * pm,unsigned long clock)462 void pm_switch_to_clock(volatile avr32_pm_t *pm, unsigned long clock)
463 {
464   // Read
465   u_avr32_pm_mcctrl_t u_avr32_pm_mcctrl = {pm->mcctrl};
466   // Modify
467   u_avr32_pm_mcctrl.MCCTRL.mcsel = clock;
468   // Write back
469   pm->mcctrl = u_avr32_pm_mcctrl.mcctrl;
470 }
471 
472 
pm_switch_to_osc0(volatile avr32_pm_t * pm,unsigned int fosc0,unsigned int startup)473 void pm_switch_to_osc0(volatile avr32_pm_t *pm, unsigned int fosc0, unsigned int startup)
474 {
475   pm_enable_osc0_crystal(pm, fosc0);            // Enable the Osc0 in crystal mode
476   pm_enable_clk0(pm, startup);                  // Crystal startup time - This parameter is critical and depends on the characteristics of the crystal
477   pm_switch_to_clock(pm, AVR32_PM_MCSEL_OSC0);  // Then switch main clock to Osc0
478 }
479 
480 
pm_bod_enable_irq(volatile avr32_pm_t * pm)481 void pm_bod_enable_irq(volatile avr32_pm_t *pm)
482 {
483   pm->ier = AVR32_PM_IER_BODDET_MASK;
484 }
485 
486 
pm_bod_disable_irq(volatile avr32_pm_t * pm)487 void pm_bod_disable_irq(volatile avr32_pm_t *pm)
488 {
489   bool global_interrupt_enabled = cpu_irq_is_enabled();
490 
491   if (global_interrupt_enabled) cpu_irq_disable();
492   pm->idr = AVR32_PM_IDR_BODDET_MASK;
493   pm->isr;
494   if (global_interrupt_enabled) cpu_irq_enable();
495 }
496 
497 
pm_bod_clear_irq(volatile avr32_pm_t * pm)498 void pm_bod_clear_irq(volatile avr32_pm_t *pm)
499 {
500   pm->icr = AVR32_PM_ICR_BODDET_MASK;
501 }
502 
503 
pm_bod_get_irq_status(volatile avr32_pm_t * pm)504 unsigned long pm_bod_get_irq_status(volatile avr32_pm_t *pm)
505 {
506   return ((pm->isr & AVR32_PM_ISR_BODDET_MASK) != 0);
507 }
508 
509 
pm_bod_get_irq_enable_bit(volatile avr32_pm_t * pm)510 unsigned long pm_bod_get_irq_enable_bit(volatile avr32_pm_t *pm)
511 {
512   return ((pm->imr & AVR32_PM_IMR_BODDET_MASK) != 0);
513 }
514 
515 
pm_bod_get_level(volatile avr32_pm_t * pm)516 unsigned long pm_bod_get_level(volatile avr32_pm_t *pm)
517 {
518   return (pm->bod & AVR32_PM_BOD_LEVEL_MASK) >> AVR32_PM_BOD_LEVEL_OFFSET;
519 }
520 
521 
pm_read_gplp(volatile avr32_pm_t * pm,unsigned long gplp)522 unsigned long pm_read_gplp(volatile avr32_pm_t *pm, unsigned long gplp)
523 {
524   return pm->gplp[gplp];
525 }
526 
527 
pm_write_gplp(volatile avr32_pm_t * pm,unsigned long gplp,unsigned long value)528 void pm_write_gplp(volatile avr32_pm_t *pm, unsigned long gplp, unsigned long value)
529 {
530   pm->gplp[gplp] = value;
531 }
532 
533 
pm_enable_module(volatile avr32_pm_t * pm,unsigned long module)534 long pm_enable_module(volatile avr32_pm_t *pm, unsigned long module)
535 {
536   unsigned long domain = module>>5;
537   unsigned long *regptr = (unsigned long*)(&(pm->cpumask) + domain);
538 
539   // Implementation-specific shortcut: the ckMASK registers are contiguous and
540   // memory-mapped in that order: CPUMASK, HSBMASK, PBAMASK, PBBMASK.
541 
542   *regptr |= (1<<(module%32));
543 
544   return PASS;
545 }
546 
pm_disable_module(volatile avr32_pm_t * pm,unsigned long module)547 long pm_disable_module(volatile avr32_pm_t *pm, unsigned long module)
548 {
549   unsigned long domain = module>>5;
550   unsigned long *regptr = (unsigned long*)(&(pm->cpumask) + domain);
551 
552   // Implementation-specific shortcut: the ckMASK registers are contiguous and
553   // memory-mapped in that order: CPUMASK, HSBMASK, PBAMASK, PBBMASK.
554 
555   *regptr &= ~(1<<(module%32));
556 
557   return PASS;
558 }
559