]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M4F_ATSAM4E_Atmel_Studio/src/ASF/sam/drivers/pmc/pmc.c
28565bbbec1af011f88ffbbae68f2747af2b91f8
[freertos] / FreeRTOS / Demo / CORTEX_M4F_ATSAM4E_Atmel_Studio / src / ASF / sam / drivers / pmc / pmc.c
1 /**\r
2  * \file\r
3  *\r
4  * \brief Power Management Controller (PMC) driver for SAM.\r
5  *\r
6  * Copyright (c) 2011 - 2013 Atmel Corporation. All rights reserved.\r
7  *\r
8  * \asf_license_start\r
9  *\r
10  * \page License\r
11  *\r
12  * Redistribution and use in source and binary forms, with or without\r
13  * modification, are permitted provided that the following conditions are met:\r
14  *\r
15  * 1. Redistributions of source code must retain the above copyright notice,\r
16  *    this list of conditions and the following disclaimer.\r
17  *\r
18  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
19  *    this list of conditions and the following disclaimer in the documentation\r
20  *    and/or other materials provided with the distribution.\r
21  *\r
22  * 3. The name of Atmel may not be used to endorse or promote products derived\r
23  *    from this software without specific prior written permission.\r
24  *\r
25  * 4. This software may only be redistributed and used in connection with an\r
26  *    Atmel microcontroller product.\r
27  *\r
28  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
29  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
31  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
32  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
36  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
37  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
38  * POSSIBILITY OF SUCH DAMAGE.\r
39  *\r
40  * \asf_license_stop\r
41  *\r
42  */\r
43 \r
44 #include "pmc.h"\r
45 \r
46 #if (SAM3N)\r
47 # define MAX_PERIPH_ID    31\r
48 #elif (SAM3XA)\r
49 # define MAX_PERIPH_ID    44\r
50 #elif (SAM3U)\r
51 # define MAX_PERIPH_ID    29\r
52 #elif (SAM3S || SAM4S)\r
53 # define MAX_PERIPH_ID    34\r
54 #elif (SAM4E)\r
55 # define MAX_PERIPH_ID    47\r
56 #elif (SAM4N)\r
57 # define MAX_PERIPH_ID    31\r
58 #endif\r
59 \r
60 /// @cond 0\r
61 /**INDENT-OFF**/\r
62 #ifdef __cplusplus\r
63 extern "C" {\r
64 #endif\r
65 /**INDENT-ON**/\r
66 /// @endcond\r
67 \r
68 /**\r
69  * \defgroup sam_drivers_pmc_group Power Management Controller (PMC)\r
70  *\r
71  * \par Purpose\r
72  *\r
73  * The Power Management Controller (PMC) optimizes power consumption by\r
74  * controlling all system and user peripheral clocks. The PMC enables/disables\r
75  * the clock inputs to many of the peripherals and the Cortex-M Processor.\r
76  *\r
77  * @{\r
78  */\r
79 \r
80 /**\r
81  * \brief Set the prescaler of the MCK.\r
82  *\r
83  * \param ul_pres Prescaler value.\r
84  */\r
85 void pmc_mck_set_prescaler(uint32_t ul_pres)\r
86 {\r
87         PMC->PMC_MCKR =\r
88                         (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;\r
89         while (!(PMC->PMC_SR & PMC_SR_MCKRDY));\r
90 }\r
91 \r
92 /**\r
93  * \brief Set the source of the MCK.\r
94  *\r
95  * \param ul_source Source selection value.\r
96  */\r
97 void pmc_mck_set_source(uint32_t ul_source)\r
98 {\r
99         PMC->PMC_MCKR =\r
100                         (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | ul_source;\r
101         while (!(PMC->PMC_SR & PMC_SR_MCKRDY));\r
102 }\r
103 \r
104 /**\r
105  * \brief Switch master clock source selection to slow clock.\r
106  *\r
107  * \param ul_pres Processor clock prescaler.\r
108  *\r
109  * \retval 0 Success.\r
110  * \retval 1 Timeout error.\r
111  */\r
112 uint32_t pmc_switch_mck_to_sclk(uint32_t ul_pres)\r
113 {\r
114         uint32_t ul_timeout;\r
115 \r
116         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |\r
117                         PMC_MCKR_CSS_SLOW_CLK;\r
118         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
119                         --ul_timeout) {\r
120                 if (ul_timeout == 0) {\r
121                         return 1;\r
122                 }\r
123         }\r
124 \r
125         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;\r
126         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
127                         --ul_timeout) {\r
128                 if (ul_timeout == 0) {\r
129                         return 1;\r
130                 }\r
131         }\r
132 \r
133         return 0;\r
134 }\r
135 \r
136 /**\r
137  * \brief Switch master clock source selection to main clock.\r
138  *\r
139  * \param ul_pres Processor clock prescaler.\r
140  *\r
141  * \retval 0 Success.\r
142  * \retval 1 Timeout error.\r
143  */\r
144 uint32_t pmc_switch_mck_to_mainck(uint32_t ul_pres)\r
145 {\r
146         uint32_t ul_timeout;\r
147 \r
148         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |\r
149                         PMC_MCKR_CSS_MAIN_CLK;\r
150         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
151                         --ul_timeout) {\r
152                 if (ul_timeout == 0) {\r
153                         return 1;\r
154                 }\r
155         }\r
156 \r
157         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;\r
158         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
159                         --ul_timeout) {\r
160                 if (ul_timeout == 0) {\r
161                         return 1;\r
162                 }\r
163         }\r
164 \r
165         return 0;\r
166 }\r
167 \r
168 /**\r
169  * \brief Switch master clock source selection to PLLA clock.\r
170  *\r
171  * \param ul_pres Processor clock prescaler.\r
172  *\r
173  * \retval 0 Success.\r
174  * \retval 1 Timeout error.\r
175  */\r
176 uint32_t pmc_switch_mck_to_pllack(uint32_t ul_pres)\r
177 {\r
178         uint32_t ul_timeout;\r
179 \r
180         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;\r
181         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
182                         --ul_timeout) {\r
183                 if (ul_timeout == 0) {\r
184                         return 1;\r
185                 }\r
186         }\r
187 \r
188         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |\r
189                         PMC_MCKR_CSS_PLLA_CLK;\r
190 \r
191         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
192                         --ul_timeout) {\r
193                 if (ul_timeout == 0) {\r
194                         return 1;\r
195                 }\r
196         }\r
197 \r
198         return 0;\r
199 }\r
200 \r
201 #if (SAM3S || SAM4S)\r
202 /**\r
203  * \brief Switch master clock source selection to PLLB clock.\r
204  *\r
205  * \param ul_pres Processor clock prescaler.\r
206  *\r
207  * \retval 0 Success.\r
208  * \retval 1 Timeout error.\r
209  */\r
210 uint32_t pmc_switch_mck_to_pllbck(uint32_t ul_pres)\r
211 {\r
212         uint32_t ul_timeout;\r
213 \r
214         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;\r
215         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
216                         --ul_timeout) {\r
217                 if (ul_timeout == 0) {\r
218                         return 1;\r
219                 }\r
220         }\r
221 \r
222         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |\r
223                         PMC_MCKR_CSS_PLLB_CLK;\r
224         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
225                         --ul_timeout) {\r
226                 if (ul_timeout == 0) {\r
227                         return 1;\r
228                 }\r
229         }\r
230 \r
231         return 0;\r
232 }\r
233 #endif\r
234 \r
235 #if (SAM3XA || SAM3U)\r
236 /**\r
237  * \brief Switch master clock source selection to UPLL clock.\r
238  *\r
239  * \param ul_pres Processor clock prescaler.\r
240  *\r
241  * \retval 0 Success.\r
242  * \retval 1 Timeout error.\r
243  */\r
244 uint32_t pmc_switch_mck_to_upllck(uint32_t ul_pres)\r
245 {\r
246         uint32_t ul_timeout;\r
247 \r
248         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;\r
249         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
250                         --ul_timeout) {\r
251                 if (ul_timeout == 0) {\r
252                         return 1;\r
253                 }\r
254         }\r
255 \r
256         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |\r
257                         PMC_MCKR_CSS_UPLL_CLK;\r
258         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
259                         --ul_timeout) {\r
260                 if (ul_timeout == 0) {\r
261                         return 1;\r
262                 }\r
263         }\r
264 \r
265         return 0;\r
266 }\r
267 #endif\r
268 \r
269 /**\r
270  * \brief Switch slow clock source selection to external 32k (Xtal or Bypass).\r
271  *\r
272  * \note This function disables the PLLs.\r
273  *\r
274  * \note Switching SCLK back to 32krc is only possible by shutting down the\r
275  *       VDDIO power supply.\r
276  *\r
277  * \param ul_bypass 0 for Xtal, 1 for bypass.\r
278  */\r
279 void pmc_switch_sclk_to_32kxtal(uint32_t ul_bypass)\r
280 {\r
281         /* Set Bypass mode if required */\r
282         if (ul_bypass == 1) {\r
283                 SUPC->SUPC_MR |= SUPC_MR_KEY(SUPC_KEY_VALUE) |\r
284                         SUPC_MR_OSCBYPASS;\r
285         }\r
286 \r
287         SUPC->SUPC_CR = SUPC_CR_KEY(SUPC_KEY_VALUE) | SUPC_CR_XTALSEL;\r
288 }\r
289 \r
290 /**\r
291  * \brief Check if the external 32k Xtal is ready.\r
292  *\r
293  * \retval 1 External 32k Xtal is ready.\r
294  * \retval 0 External 32k Xtal is not ready.\r
295  */\r
296 uint32_t pmc_osc_is_ready_32kxtal(void)\r
297 {\r
298         return ((SUPC->SUPC_SR & SUPC_SR_OSCSEL)\r
299                         && (PMC->PMC_SR & PMC_SR_OSCSELS));\r
300 }\r
301 \r
302 /**\r
303  * \brief Switch main clock source selection to internal fast RC.\r
304  *\r
305  * \param ul_moscrcf Fast RC oscillator(4/8/12Mhz).\r
306  *\r
307  * \retval 0 Success.\r
308  * \retval 1 Timeout error.\r
309  * \retval 2 Invalid frequency.\r
310  */\r
311 void pmc_switch_mainck_to_fastrc(uint32_t ul_moscrcf)\r
312 {\r
313         uint32_t ul_needXTEN = 0;\r
314 \r
315         /* Enable Fast RC oscillator but DO NOT switch to RC now */\r
316         if (PMC->CKGR_MOR & CKGR_MOR_MOSCXTEN) {\r
317                 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCF_Msk) |\r
318                                 PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCRCEN |\r
319                                 ul_moscrcf;\r
320         } else {\r
321                 ul_needXTEN = 1;\r
322                 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCF_Msk) |\r
323                                 PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCRCEN |\r
324                                 CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCXTST_Msk |\r
325                                 ul_moscrcf;\r
326         }\r
327 \r
328         /* Wait the Fast RC to stabilize */\r
329         while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));\r
330 \r
331         /* Switch to Fast RC */\r
332         PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) |\r
333                         PMC_CKGR_MOR_KEY_VALUE;\r
334 \r
335         /* Disable xtal oscillator */\r
336         if (ul_needXTEN) {\r
337                 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |\r
338                                 PMC_CKGR_MOR_KEY_VALUE;\r
339         }\r
340 }\r
341 \r
342 /**\r
343  * \brief Enable fast RC oscillator.\r
344  *\r
345  * \param ul_rc Fast RC oscillator(4/8/12Mhz).\r
346  */\r
347 void pmc_osc_enable_fastrc(uint32_t ul_rc)\r
348 {\r
349         /* Enable Fast RC oscillator but DO NOT switch to RC now.\r
350          * Keep MOSCSEL to 1 */\r
351         PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCSEL |\r
352                         CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCRCEN | ul_rc;\r
353         /* Wait the Fast RC to stabilize */\r
354         while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));\r
355 }\r
356 \r
357 /**\r
358  * \brief Disable the internal fast RC.\r
359  */\r
360 void pmc_osc_disable_fastrc(void)\r
361 {\r
362         /* Disable Fast RC oscillator */\r
363         PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCEN &\r
364                                         ~CKGR_MOR_MOSCRCF_Msk)\r
365                                 | PMC_CKGR_MOR_KEY_VALUE;\r
366 }\r
367 \r
368 /**\r
369  * \brief Check if the main fastrc is ready.\r
370  *\r
371  * \retval 0 Xtal is not ready, otherwise ready.\r
372  */\r
373 uint32_t pmc_osc_is_ready_fastrc(void)\r
374 {\r
375         return (PMC->PMC_SR & PMC_SR_MOSCRCS);\r
376 }\r
377 \r
378 /**\r
379  * \brief Enable main XTAL oscillator.\r
380  *\r
381  * \param ul_xtal_startup_time Xtal start-up time, in number of slow clocks.\r
382  */\r
383 void pmc_osc_enable_main_xtal(uint32_t ul_xtal_startup_time)\r
384 {\r
385         uint32_t mor = PMC->CKGR_MOR;\r
386         mor &= ~(CKGR_MOR_MOSCXTBY|CKGR_MOR_MOSCXTEN);\r
387         mor |= PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCXTEN |\r
388                         CKGR_MOR_MOSCXTST(ul_xtal_startup_time);\r
389         PMC->CKGR_MOR = mor;\r
390         /* Wait the main Xtal to stabilize */\r
391         while (!(PMC->PMC_SR & PMC_SR_MOSCXTS));\r
392 }\r
393 \r
394 /**\r
395  * \brief Bypass main XTAL.\r
396  */\r
397 void pmc_osc_bypass_main_xtal(void)\r
398 {\r
399         uint32_t mor = PMC->CKGR_MOR;\r
400         mor &= ~(CKGR_MOR_MOSCXTBY|CKGR_MOR_MOSCXTEN);\r
401         mor |= PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCXTBY;\r
402         /* Enable Crystal oscillator but DO NOT switch now. Keep MOSCSEL to 0 */\r
403         PMC->CKGR_MOR = mor;\r
404         /* The MOSCXTS in PMC_SR is automatically set */\r
405 }\r
406 \r
407 /**\r
408  * \brief Disable the main Xtal.\r
409  */\r
410 void pmc_osc_disable_main_xtal(void)\r
411 {\r
412         uint32_t mor = PMC->CKGR_MOR;\r
413         mor &= ~(CKGR_MOR_MOSCXTBY|CKGR_MOR_MOSCXTEN);\r
414         PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | mor;\r
415 }\r
416 \r
417 /**\r
418  * \brief Check if the main crystal is bypassed.\r
419  *\r
420  * \retval 0 Xtal is bypassed, otherwise not.\r
421  */\r
422 uint32_t pmc_osc_is_bypassed_main_xtal(void)\r
423 {\r
424         return (PMC->CKGR_MOR & CKGR_MOR_MOSCXTBY);\r
425 }\r
426 \r
427 /**\r
428  * \brief Check if the main crystal is ready.\r
429  *\r
430  * \note If main crystal is bypassed, it's always ready.\r
431  *\r
432  * \retval 0 main crystal is not ready, otherwise ready.\r
433  */\r
434 uint32_t pmc_osc_is_ready_main_xtal(void)\r
435 {\r
436         return (PMC->PMC_SR & PMC_SR_MOSCXTS);\r
437 }\r
438 \r
439 /**\r
440  * \brief Switch main clock source selection to external Xtal/Bypass.\r
441  *\r
442  * \note The function may switch MCK to SCLK if MCK source is MAINCK to avoid\r
443  *       any system crash.\r
444  *\r
445  * \note If used in Xtal mode, the Xtal is automatically enabled.\r
446  *\r
447  * \param ul_bypass 0 for Xtal, 1 for bypass.\r
448  *\r
449  * \retval 0 Success.\r
450  * \retval 1 Timeout error.\r
451  */\r
452 void pmc_switch_mainck_to_xtal(uint32_t ul_bypass,\r
453                 uint32_t ul_xtal_startup_time)\r
454 {\r
455         /* Enable Main Xtal oscillator */\r
456         if (ul_bypass) {\r
457                 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |\r
458                                 PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCXTBY |\r
459                                 CKGR_MOR_MOSCSEL;\r
460         } else {\r
461                 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) |\r
462                                 PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCXTEN |\r
463                                 CKGR_MOR_MOSCXTST(ul_xtal_startup_time);\r
464                 /* Wait the Xtal to stabilize */\r
465                 while (!(PMC->PMC_SR & PMC_SR_MOSCXTS));\r
466 \r
467                 PMC->CKGR_MOR |= PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCSEL;\r
468         }\r
469 }\r
470 \r
471 /**\r
472  * \brief Disable the external Xtal.\r
473  *\r
474  * \param ul_bypass 0 for Xtal, 1 for bypass.\r
475  */\r
476 void pmc_osc_disable_xtal(uint32_t ul_bypass)\r
477 {\r
478         /* Disable xtal oscillator */\r
479         if (ul_bypass) {\r
480                 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) |\r
481                                 PMC_CKGR_MOR_KEY_VALUE;\r
482         } else {\r
483                 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |\r
484                                 PMC_CKGR_MOR_KEY_VALUE;\r
485         }\r
486 }\r
487 \r
488 /**\r
489  * \brief Check if the MAINCK is ready. Depending on MOSCEL, MAINCK can be one\r
490  * of Xtal, bypass or internal RC.\r
491  *\r
492  * \retval 1 Xtal is ready.\r
493  * \retval 0 Xtal is not ready.\r
494  */\r
495 uint32_t pmc_osc_is_ready_mainck(void)\r
496 {\r
497         return PMC->PMC_SR & PMC_SR_MOSCSELS;\r
498 }\r
499 \r
500 /**\r
501  * \brief Select Main Crystal or internal RC as main clock source.\r
502  *\r
503  * \note This function will not enable/disable RC or Main Crystal.\r
504  *\r
505  * \param ul_xtal_rc 0 internal RC is selected, otherwise Main Crystal.\r
506  */\r
507 void pmc_mainck_osc_select(uint32_t ul_xtal_rc)\r
508 {\r
509         uint32_t mor = PMC->CKGR_MOR;\r
510         if (ul_xtal_rc) {\r
511                 mor |=  CKGR_MOR_MOSCSEL;\r
512         } else {\r
513                 mor &= ~CKGR_MOR_MOSCSEL;\r
514         }\r
515         PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | mor;\r
516 }\r
517 \r
518 /**\r
519  * \brief Enable PLLA clock.\r
520  *\r
521  * \param mula PLLA multiplier.\r
522  * \param pllacount PLLA counter.\r
523  * \param diva Divider.\r
524  */\r
525 void pmc_enable_pllack(uint32_t mula, uint32_t pllacount, uint32_t diva)\r
526 {\r
527         /* first disable the PLL to unlock the lock */\r
528         pmc_disable_pllack();\r
529 \r
530         PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_DIVA(diva) |\r
531                         CKGR_PLLAR_PLLACOUNT(pllacount) | CKGR_PLLAR_MULA(mula);\r
532         while ((PMC->PMC_SR & PMC_SR_LOCKA) == 0);\r
533 }\r
534 \r
535 /**\r
536  * \brief Disable PLLA clock.\r
537  */\r
538 void pmc_disable_pllack(void)\r
539 {\r
540         PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0);\r
541 }\r
542 \r
543 /**\r
544  * \brief Is PLLA locked?\r
545  *\r
546  * \retval 0 Not locked.\r
547  * \retval 1 Locked.\r
548  */\r
549 uint32_t pmc_is_locked_pllack(void)\r
550 {\r
551         return (PMC->PMC_SR & PMC_SR_LOCKA);\r
552 }\r
553 \r
554 #if (SAM3S || SAM4S)\r
555 /**\r
556  * \brief Enable PLLB clock.\r
557  *\r
558  * \param mulb PLLB multiplier.\r
559  * \param pllbcount PLLB counter.\r
560  * \param divb Divider.\r
561  */\r
562 void pmc_enable_pllbck(uint32_t mulb, uint32_t pllbcount, uint32_t divb)\r
563 {\r
564         /* first disable the PLL to unlock the lock */\r
565         pmc_disable_pllbck();\r
566 \r
567         PMC->CKGR_PLLBR =\r
568                         CKGR_PLLBR_DIVB(divb) | CKGR_PLLBR_PLLBCOUNT(pllbcount)\r
569                         | CKGR_PLLBR_MULB(mulb);\r
570         while ((PMC->PMC_SR & PMC_SR_LOCKB) == 0);\r
571 }\r
572 \r
573 /**\r
574  * \brief Disable PLLB clock.\r
575  */\r
576 void pmc_disable_pllbck(void)\r
577 {\r
578         PMC->CKGR_PLLBR = CKGR_PLLBR_MULB(0);\r
579 }\r
580 \r
581 /**\r
582  * \brief Is PLLB locked?\r
583  *\r
584  * \retval 0 Not locked.\r
585  * \retval 1 Locked.\r
586  */\r
587 uint32_t pmc_is_locked_pllbck(void)\r
588 {\r
589         return (PMC->PMC_SR & PMC_SR_LOCKB);\r
590 }\r
591 #endif\r
592 \r
593 #if (SAM3XA || SAM3U)\r
594 /**\r
595  * \brief Enable UPLL clock.\r
596  */\r
597 void pmc_enable_upll_clock(void)\r
598 {\r
599         PMC->CKGR_UCKR = CKGR_UCKR_UPLLCOUNT(3) | CKGR_UCKR_UPLLEN;\r
600 \r
601         /* Wait UTMI PLL Lock Status */\r
602         while (!(PMC->PMC_SR & PMC_SR_LOCKU));\r
603 }\r
604 \r
605 /**\r
606  * \brief Disable UPLL clock.\r
607  */\r
608 void pmc_disable_upll_clock(void)\r
609 {\r
610         PMC->CKGR_UCKR &= ~CKGR_UCKR_UPLLEN;\r
611 }\r
612 \r
613 /**\r
614  * \brief Is UPLL locked?\r
615  *\r
616  * \retval 0 Not locked.\r
617  * \retval 1 Locked.\r
618  */\r
619 uint32_t pmc_is_locked_upll(void)\r
620 {\r
621         return (PMC->PMC_SR & PMC_SR_LOCKU);\r
622 }\r
623 #endif\r
624 \r
625 /**\r
626  * \brief Enable the specified peripheral clock.\r
627  *\r
628  * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).\r
629  *\r
630  * \param ul_id Peripheral ID (ID_xxx).\r
631  *\r
632  * \retval 0 Success.\r
633  * \retval 1 Invalid parameter.\r
634  */\r
635 uint32_t pmc_enable_periph_clk(uint32_t ul_id)\r
636 {\r
637         if (ul_id > MAX_PERIPH_ID) {\r
638                 return 1;\r
639         }\r
640 \r
641         if (ul_id < 32) {\r
642                 if ((PMC->PMC_PCSR0 & (1u << ul_id)) != (1u << ul_id)) {\r
643                         PMC->PMC_PCER0 = 1 << ul_id;\r
644                 }\r
645 #if (SAM3S || SAM3XA || SAM4S || SAM4E)\r
646         } else {\r
647                 ul_id -= 32;\r
648                 if ((PMC->PMC_PCSR1 & (1u << ul_id)) != (1u << ul_id)) {\r
649                         PMC->PMC_PCER1 = 1 << ul_id;\r
650                 }\r
651 #endif\r
652         }\r
653 \r
654         return 0;\r
655 }\r
656 \r
657 /**\r
658  * \brief Disable the specified peripheral clock.\r
659  *\r
660  * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).\r
661  *\r
662  * \param ul_id Peripheral ID (ID_xxx).\r
663  *\r
664  * \retval 0 Success.\r
665  * \retval 1 Invalid parameter.\r
666  */\r
667 uint32_t pmc_disable_periph_clk(uint32_t ul_id)\r
668 {\r
669         if (ul_id > MAX_PERIPH_ID) {\r
670                 return 1;\r
671         }\r
672 \r
673         if (ul_id < 32) {\r
674                 if ((PMC->PMC_PCSR0 & (1u << ul_id)) == (1u << ul_id)) {\r
675                         PMC->PMC_PCDR0 = 1 << ul_id;\r
676                 }\r
677 #if (SAM3S || SAM3XA || SAM4S || SAM4E)\r
678         } else {\r
679                 ul_id -= 32;\r
680                 if ((PMC->PMC_PCSR1 & (1u << ul_id)) == (1u << ul_id)) {\r
681                         PMC->PMC_PCDR1 = 1 << ul_id;\r
682                 }\r
683 #endif\r
684         }\r
685         return 0;\r
686 }\r
687 \r
688 /**\r
689  * \brief Enable all peripheral clocks.\r
690  */\r
691 void pmc_enable_all_periph_clk(void)\r
692 {\r
693         PMC->PMC_PCER0 = PMC_MASK_STATUS0;\r
694         while ((PMC->PMC_PCSR0 & PMC_MASK_STATUS0) != PMC_MASK_STATUS0);\r
695 \r
696 #if (SAM3S || SAM3XA || SAM4S || SAM4E)\r
697         PMC->PMC_PCER1 = PMC_MASK_STATUS1;\r
698         while ((PMC->PMC_PCSR1 & PMC_MASK_STATUS1) != PMC_MASK_STATUS1);\r
699 #endif\r
700 }\r
701 \r
702 /**\r
703  * \brief Disable all peripheral clocks.\r
704  */\r
705 void pmc_disable_all_periph_clk(void)\r
706 {\r
707         PMC->PMC_PCDR0 = PMC_MASK_STATUS0;\r
708         while ((PMC->PMC_PCSR0 & PMC_MASK_STATUS0) != 0);\r
709 \r
710 #if (SAM3S || SAM3XA || SAM4S || SAM4E)\r
711         PMC->PMC_PCDR1 = PMC_MASK_STATUS1;\r
712         while ((PMC->PMC_PCSR1 & PMC_MASK_STATUS1) != 0);\r
713 #endif\r
714 }\r
715 \r
716 /**\r
717  * \brief Check if the specified peripheral clock is enabled.\r
718  *\r
719  * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).\r
720  *\r
721  * \param ul_id Peripheral ID (ID_xxx).\r
722  *\r
723  * \retval 0 Peripheral clock is disabled or unknown.\r
724  * \retval 1 Peripheral clock is enabled.\r
725  */\r
726 uint32_t pmc_is_periph_clk_enabled(uint32_t ul_id)\r
727 {\r
728         if (ul_id > MAX_PERIPH_ID) {\r
729                 return 0;\r
730         }\r
731 \r
732 #if (SAM3S || SAM3XA || SAM4S || SAM4E)\r
733         if (ul_id < 32) {\r
734 #endif\r
735                 if ((PMC->PMC_PCSR0 & (1u << ul_id))) {\r
736                         return 1;\r
737                 } else {\r
738                         return 0;\r
739                 }\r
740 #if (SAM3S || SAM3XA || SAM4S || SAM4E)\r
741         } else {\r
742                 ul_id -= 32;\r
743                 if ((PMC->PMC_PCSR1 & (1u << ul_id))) {\r
744                         return 1;\r
745                 } else {\r
746                         return 0;\r
747                 }\r
748         }\r
749 #endif\r
750 }\r
751 \r
752 /**\r
753  * \brief Set the prescaler for the specified programmable clock.\r
754  *\r
755  * \param ul_id Peripheral ID.\r
756  * \param ul_pres Prescaler value.\r
757  */\r
758 void pmc_pck_set_prescaler(uint32_t ul_id, uint32_t ul_pres)\r
759 {\r
760         PMC->PMC_PCK[ul_id] =\r
761                         (PMC->PMC_PCK[ul_id] & ~PMC_PCK_PRES_Msk) | ul_pres;\r
762         while ((PMC->PMC_SCER & (PMC_SCER_PCK0 << ul_id))\r
763                         && !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)));\r
764 }\r
765 \r
766 /**\r
767  * \brief Set the source oscillator for the specified programmable clock.\r
768  *\r
769  * \param ul_id Peripheral ID.\r
770  * \param ul_source Source selection value.\r
771  */\r
772 void pmc_pck_set_source(uint32_t ul_id, uint32_t ul_source)\r
773 {\r
774         PMC->PMC_PCK[ul_id] =\r
775                         (PMC->PMC_PCK[ul_id] & ~PMC_PCK_CSS_Msk) | ul_source;\r
776         while ((PMC->PMC_SCER & (PMC_SCER_PCK0 << ul_id))\r
777                         && !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)));\r
778 }\r
779 \r
780 /**\r
781  * \brief Switch programmable clock source selection to slow clock.\r
782  *\r
783  * \param ul_id Id of the programmable clock.\r
784  * \param ul_pres Programmable clock prescaler.\r
785  *\r
786  * \retval 0 Success.\r
787  * \retval 1 Timeout error.\r
788  */\r
789 uint32_t pmc_switch_pck_to_sclk(uint32_t ul_id, uint32_t ul_pres)\r
790 {\r
791         uint32_t ul_timeout;\r
792 \r
793         PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_SLOW_CLK | ul_pres;\r
794         for (ul_timeout = PMC_TIMEOUT;\r
795         !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)); --ul_timeout) {\r
796                 if (ul_timeout == 0) {\r
797                         return 1;\r
798                 }\r
799         }\r
800 \r
801         return 0;\r
802 }\r
803 \r
804 /**\r
805  * \brief Switch programmable clock source selection to main clock.\r
806  *\r
807  * \param ul_id Id of the programmable clock.\r
808  * \param ul_pres Programmable clock prescaler.\r
809  *\r
810  * \retval 0 Success.\r
811  * \retval 1 Timeout error.\r
812  */\r
813 uint32_t pmc_switch_pck_to_mainck(uint32_t ul_id, uint32_t ul_pres)\r
814 {\r
815         uint32_t ul_timeout;\r
816 \r
817         PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_MAIN_CLK | ul_pres;\r
818         for (ul_timeout = PMC_TIMEOUT;\r
819         !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)); --ul_timeout) {\r
820                 if (ul_timeout == 0) {\r
821                         return 1;\r
822                 }\r
823         }\r
824 \r
825         return 0;\r
826 }\r
827 \r
828 /**\r
829  * \brief Switch programmable clock source selection to PLLA clock.\r
830  *\r
831  * \param ul_id Id of the programmable clock.\r
832  * \param ul_pres Programmable clock prescaler.\r
833  *\r
834  * \retval 0 Success.\r
835  * \retval 1 Timeout error.\r
836  */\r
837 uint32_t pmc_switch_pck_to_pllack(uint32_t ul_id, uint32_t ul_pres)\r
838 {\r
839         uint32_t ul_timeout;\r
840 \r
841         PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_PLLA_CLK | ul_pres;\r
842         for (ul_timeout = PMC_TIMEOUT;\r
843         !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)); --ul_timeout) {\r
844                 if (ul_timeout == 0) {\r
845                         return 1;\r
846                 }\r
847         }\r
848 \r
849         return 0;\r
850 }\r
851 \r
852 #if (SAM3S || SAM4S)\r
853 /**\r
854  * \brief Switch programmable clock source selection to PLLB clock.\r
855  *\r
856  * \param ul_id Id of the programmable clock.\r
857  * \param ul_pres Programmable clock prescaler.\r
858  *\r
859  * \retval 0 Success.\r
860  * \retval 1 Timeout error.\r
861  */\r
862 uint32_t pmc_switch_pck_to_pllbck(uint32_t ul_id, uint32_t ul_pres)\r
863 {\r
864         uint32_t ul_timeout;\r
865 \r
866         PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_PLLB_CLK | ul_pres;\r
867         for (ul_timeout = PMC_TIMEOUT;\r
868                         !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id));\r
869                         --ul_timeout) {\r
870                 if (ul_timeout == 0) {\r
871                         return 1;\r
872                 }\r
873         }\r
874 \r
875         return 0;\r
876 }\r
877 #endif\r
878 \r
879 #if (SAM3XA || SAM3U)\r
880 /**\r
881  * \brief Switch programmable clock source selection to UPLL clock.\r
882  *\r
883  * \param ul_id Id of the programmable clock.\r
884  * \param ul_pres Programmable clock prescaler.\r
885  *\r
886  * \retval 0 Success.\r
887  * \retval 1 Timeout error.\r
888  */\r
889 uint32_t pmc_switch_pck_to_upllck(uint32_t ul_id, uint32_t ul_pres)\r
890 {\r
891         uint32_t ul_timeout;\r
892 \r
893         PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_UPLL_CLK | ul_pres;\r
894         for (ul_timeout = PMC_TIMEOUT;\r
895                         !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id));\r
896                         --ul_timeout) {\r
897                 if (ul_timeout == 0) {\r
898                         return 1;\r
899                 }\r
900         }\r
901 \r
902         return 0;\r
903 }\r
904 #endif\r
905 \r
906 /**\r
907  * \brief Enable the specified programmable clock.\r
908  *\r
909  * \param ul_id Id of the programmable clock.\r
910  */\r
911 void pmc_enable_pck(uint32_t ul_id)\r
912 {\r
913         PMC->PMC_SCER = PMC_SCER_PCK0 << ul_id;\r
914 }\r
915 \r
916 /**\r
917  * \brief Disable the specified programmable clock.\r
918  *\r
919  * \param ul_id Id of the programmable clock.\r
920  */\r
921 void pmc_disable_pck(uint32_t ul_id)\r
922 {\r
923         PMC->PMC_SCDR = PMC_SCER_PCK0 << ul_id;\r
924 }\r
925 \r
926 /**\r
927  * \brief Enable all programmable clocks.\r
928  */\r
929 void pmc_enable_all_pck(void)\r
930 {\r
931         PMC->PMC_SCER = PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2;\r
932 }\r
933 \r
934 /**\r
935  * \brief Disable all programmable clocks.\r
936  */\r
937 void pmc_disable_all_pck(void)\r
938 {\r
939         PMC->PMC_SCDR = PMC_SCDR_PCK0 | PMC_SCDR_PCK1 | PMC_SCDR_PCK2;\r
940 }\r
941 \r
942 /**\r
943  * \brief Check if the specified programmable clock is enabled.\r
944  *\r
945  * \param ul_id Id of the programmable clock.\r
946  *\r
947  * \retval 0 Programmable clock is disabled or unknown.\r
948  * \retval 1 Programmable clock is enabled.\r
949  */\r
950 uint32_t pmc_is_pck_enabled(uint32_t ul_id)\r
951 {\r
952         if (ul_id > 2) {\r
953                 return 0;\r
954         }\r
955 \r
956         return (PMC->PMC_SCSR & (PMC_SCSR_PCK0 << ul_id));\r
957 }\r
958 \r
959 #if (SAM3S || SAM3XA || SAM4S || SAM4E)\r
960 /**\r
961  * \brief Switch UDP (USB) clock source selection to PLLA clock.\r
962  *\r
963  * \param ul_usbdiv Clock divisor.\r
964  */\r
965 void pmc_switch_udpck_to_pllack(uint32_t ul_usbdiv)\r
966 {\r
967         PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv);\r
968 }\r
969 #endif\r
970 \r
971 #if (SAM3S || SAM4S)\r
972 /**\r
973  * \brief Switch UDP (USB) clock source selection to PLLB clock.\r
974  *\r
975  * \param ul_usbdiv Clock divisor.\r
976  */\r
977 void pmc_switch_udpck_to_pllbck(uint32_t ul_usbdiv)\r
978 {\r
979         PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv) | PMC_USB_USBS;\r
980 }\r
981 #endif\r
982 \r
983 #if (SAM3XA)\r
984 /**\r
985  * \brief Switch UDP (USB) clock source selection to UPLL clock.\r
986  *\r
987  * \param dw_usbdiv Clock divisor.\r
988  */\r
989 void pmc_switch_udpck_to_upllck(uint32_t ul_usbdiv)\r
990 {\r
991         PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(ul_usbdiv);\r
992 }\r
993 #endif\r
994 \r
995 #if (SAM3S || SAM3XA || SAM4S || SAM4E)\r
996 /**\r
997  * \brief Enable UDP (USB) clock.\r
998  */\r
999 void pmc_enable_udpck(void)\r
1000 {\r
1001 # if (SAM3S || SAM4S || SAM4E)\r
1002         PMC->PMC_SCER = PMC_SCER_UDP;\r
1003 # else\r
1004         PMC->PMC_SCER = PMC_SCER_UOTGCLK;\r
1005 # endif\r
1006 }\r
1007 \r
1008 /**\r
1009  * \brief Disable UDP (USB) clock.\r
1010  */\r
1011 void pmc_disable_udpck(void)\r
1012 {\r
1013 # if (SAM3S || SAM4S || SAM4E)\r
1014         PMC->PMC_SCDR = PMC_SCDR_UDP;\r
1015 # else\r
1016         PMC->PMC_SCDR = PMC_SCDR_UOTGCLK;\r
1017 # endif\r
1018 }\r
1019 #endif\r
1020 \r
1021 /**\r
1022  * \brief Enable PMC interrupts.\r
1023  *\r
1024  * \param ul_sources Interrupt sources bit map.\r
1025  */\r
1026 void pmc_enable_interrupt(uint32_t ul_sources)\r
1027 {\r
1028         PMC->PMC_IER = ul_sources;\r
1029 }\r
1030 \r
1031 /**\r
1032  * \brief Disable PMC interrupts.\r
1033  *\r
1034  * \param ul_sources Interrupt sources bit map.\r
1035  */\r
1036 void pmc_disable_interrupt(uint32_t ul_sources)\r
1037 {\r
1038         PMC->PMC_IDR = ul_sources;\r
1039 }\r
1040 \r
1041 /**\r
1042  * \brief Get PMC interrupt mask.\r
1043  *\r
1044  * \return The interrupt mask value.\r
1045  */\r
1046 uint32_t pmc_get_interrupt_mask(void)\r
1047 {\r
1048         return PMC->PMC_IMR;\r
1049 }\r
1050 \r
1051 /**\r
1052  * \brief Get current status.\r
1053  *\r
1054  * \return The current PMC status.\r
1055  */\r
1056 uint32_t pmc_get_status(void)\r
1057 {\r
1058         return PMC->PMC_SR;\r
1059 }\r
1060 \r
1061 /**\r
1062  * \brief Set the wake-up inputs for fast startup mode registers\r
1063  *        (event generation).\r
1064  *\r
1065  * \param ul_inputs Wake up inputs to enable.\r
1066  */\r
1067 void pmc_set_fast_startup_input(uint32_t ul_inputs)\r
1068 {\r
1069         ul_inputs &= PMC_FAST_STARTUP_Msk;\r
1070         PMC->PMC_FSMR |= ul_inputs;\r
1071 }\r
1072 \r
1073 /**\r
1074  * \brief Clear the wake-up inputs for fast startup mode registers\r
1075  *        (remove event generation).\r
1076  *\r
1077  * \param ul_inputs Wake up inputs to disable.\r
1078  */\r
1079 void pmc_clr_fast_startup_input(uint32_t ul_inputs)\r
1080 {\r
1081         ul_inputs &= PMC_FAST_STARTUP_Msk;\r
1082         PMC->PMC_FSMR &= ~ul_inputs;\r
1083 }\r
1084 \r
1085 /**\r
1086  * \brief Enable Sleep Mode.\r
1087  * Enter condition: (WFE or WFI) + (SLEEPDEEP bit = 0) + (LPM bit = 0)\r
1088  *\r
1089  * \param uc_type 0 for wait for interrupt, 1 for wait for event.\r
1090  * \note For SAM4S and SAM4E series, since only WFI is effective, uc_type = 1\r
1091  * will be treated as uc_type = 0.\r
1092  */\r
1093 void pmc_enable_sleepmode(uint8_t uc_type)\r
1094 {\r
1095 #if !defined(SAM4S) || !defined(SAM4E) || !defined(SAM4N)\r
1096         PMC->PMC_FSMR &= (uint32_t) ~ PMC_FSMR_LPM; // Enter Sleep mode\r
1097 #endif\r
1098         SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk; // Deep sleep\r
1099 \r
1100 #if (SAM4S || SAM4E || SAM4N)\r
1101         UNUSED(uc_type);\r
1102         __WFI();\r
1103 #else\r
1104         if (uc_type == 0) {\r
1105                 __WFI();\r
1106         } else {\r
1107                 __WFE();\r
1108         }\r
1109 #endif\r
1110 }\r
1111 \r
1112 #if (SAM4S || SAM4E || SAM4N)\r
1113 static uint32_t ul_flash_in_wait_mode = PMC_WAIT_MODE_FLASH_DEEP_POWERDOWN;\r
1114 /**\r
1115  * \brief Set the embedded flash state in wait mode\r
1116  *\r
1117  * \param ul_flash_state PMC_WAIT_MODE_FLASH_STANDBY flash in standby mode,\r
1118  * PMC_WAIT_MODE_FLASH_DEEP_POWERDOWN flash in deep power down mode.\r
1119  */\r
1120 void pmc_set_flash_in_wait_mode(uint32_t ul_flash_state)\r
1121 {\r
1122         ul_flash_in_wait_mode = ul_flash_state;\r
1123 }\r
1124 \r
1125 /**\r
1126  * \brief Enable Wait Mode. Enter condition: (WAITMODE bit = 1) +\r
1127  * (SLEEPDEEP bit = 0) + FLPM\r
1128  */\r
1129 void pmc_enable_waitmode(void)\r
1130 {\r
1131         uint32_t i;\r
1132 \r
1133         /* Flash in Deep Power Down mode */\r
1134         i = PMC->PMC_FSMR;\r
1135         i &= ~PMC_FSMR_FLPM_Msk;\r
1136         i |= ul_flash_in_wait_mode;\r
1137         PMC->PMC_FSMR = i;\r
1138 \r
1139         /* Clear SLEEPDEEP bit */\r
1140         SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk;\r
1141 \r
1142         /* Backup FWS setting and set Flash Wait State at 0 */\r
1143 #if defined(ID_EFC)\r
1144         uint32_t fmr_backup;\r
1145         fmr_backup = EFC->EEFC_FMR;\r
1146         EFC->EEFC_FMR &= (uint32_t) ~ EEFC_FMR_FWS_Msk;\r
1147 #endif\r
1148 #if defined(ID_EFC0)\r
1149         uint32_t fmr0_backup;\r
1150         fmr0_backup = EFC0->EEFC_FMR;\r
1151         EFC0->EEFC_FMR &= (uint32_t) ~ EEFC_FMR_FWS_Msk;\r
1152 #endif\r
1153 #if defined(ID_EFC1)\r
1154         uint32_t fmr1_backup;\r
1155         fmr1_backup = EFC1->EEFC_FMR;\r
1156         EFC1->EEFC_FMR &= (uint32_t) ~ EEFC_FMR_FWS_Msk;\r
1157 #endif\r
1158 \r
1159         /* Set the WAITMODE bit = 1 */\r
1160         PMC->CKGR_MOR |= CKGR_MOR_KEY(0x37u) | CKGR_MOR_WAITMODE;\r
1161 \r
1162         /* Waiting for Master Clock Ready MCKRDY = 1 */\r
1163         while (!(PMC->PMC_SR & PMC_SR_MCKRDY));\r
1164 \r
1165         /* Waiting for MOSCRCEN bit cleared is strongly recommended\r
1166          * to ensure that the core will not execute undesired instructions\r
1167          */\r
1168         for (i = 0; i < 500; i++) {\r
1169                 __NOP();\r
1170         }\r
1171         while (!(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN));\r
1172 \r
1173         /* Restore EFC FMR setting */\r
1174 #if defined(ID_EFC)\r
1175         EFC->EEFC_FMR = fmr_backup;\r
1176 #endif\r
1177 #if defined(ID_EFC0)\r
1178         EFC0->EEFC_FMR = fmr0_backup;\r
1179 #endif\r
1180 #if defined(ID_EFC1)\r
1181         EFC1->EEFC_FMR = fmr1_backup;\r
1182 #endif\r
1183 }\r
1184 #else\r
1185 /**\r
1186  * \brief Enable Wait Mode. Enter condition: WFE + (SLEEPDEEP bit = 0) +\r
1187  * (LPM bit = 1)\r
1188  */\r
1189 void pmc_enable_waitmode(void)\r
1190 {\r
1191         uint32_t i;\r
1192 \r
1193         PMC->PMC_FSMR |= PMC_FSMR_LPM; /* Enter Wait mode */\r
1194         SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk; /* Deep sleep */\r
1195         __WFE();\r
1196 \r
1197         /* Waiting for MOSCRCEN bit cleared is strongly recommended\r
1198          * to ensure that the core will not execute undesired instructions\r
1199          */\r
1200         for (i = 0; i < 500; i++) {\r
1201                 __NOP();\r
1202         }\r
1203         while (!(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN));\r
1204 }\r
1205 #endif\r
1206 \r
1207 /**\r
1208  * \brief Enable Backup Mode. Enter condition: WFE/(VROFF bit = 1) +\r
1209  * (SLEEPDEEP bit = 1)\r
1210  */\r
1211 void pmc_enable_backupmode(void)\r
1212 {\r
1213         SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;\r
1214 #if (SAM4S || SAM4E || SAM4N)\r
1215         SUPC->SUPC_CR = SUPC_CR_KEY(SUPC_KEY_VALUE) | SUPC_CR_VROFF_STOP_VREG;\r
1216 #else\r
1217         __WFE();\r
1218 #endif\r
1219 }\r
1220 \r
1221 /**\r
1222  * \brief Enable Clock Failure Detector.\r
1223  */\r
1224 void pmc_enable_clock_failure_detector(void)\r
1225 {\r
1226         uint32_t ul_reg = PMC->CKGR_MOR;\r
1227 \r
1228         PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_CFDEN | ul_reg;\r
1229 }\r
1230 \r
1231 /**\r
1232  * \brief Disable Clock Failure Detector.\r
1233  */\r
1234 void pmc_disable_clock_failure_detector(void)\r
1235 {\r
1236         uint32_t ul_reg = PMC->CKGR_MOR & (~CKGR_MOR_CFDEN);\r
1237 \r
1238         PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | ul_reg;\r
1239 }\r
1240 \r
1241 #if SAM4N\r
1242 /**\r
1243  * \brief Enable Slow Crystal Oscillator Frequency Monitoring.\r
1244  */\r
1245 void pmc_enable_sclk_osc_freq_monitor(void)\r
1246 {\r
1247         uint32_t ul_reg = PMC->CKGR_MOR;\r
1248 \r
1249         PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_XT32KFME | ul_reg;\r
1250 }\r
1251 \r
1252 /**\r
1253  * \brief Disable Slow Crystal Oscillator Frequency Monitoring.\r
1254  */\r
1255 void pmc_disable_sclk_osc_freq_monitor(void)\r
1256 {\r
1257         uint32_t ul_reg = PMC->CKGR_MOR & (~CKGR_MOR_XT32KFME);\r
1258 \r
1259         PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | ul_reg;\r
1260 }\r
1261 #endif\r
1262 \r
1263 /**\r
1264  * \brief Enable or disable write protect of PMC registers.\r
1265  *\r
1266  * \param ul_enable 1 to enable, 0 to disable.\r
1267  */\r
1268 void pmc_set_writeprotect(uint32_t ul_enable)\r
1269 {\r
1270         if (ul_enable) {\r
1271                 PMC->PMC_WPMR = PMC_WPMR_WPKEY_VALUE | PMC_WPMR_WPEN;\r
1272         } else {\r
1273                 PMC->PMC_WPMR = PMC_WPMR_WPKEY_VALUE;\r
1274         }\r
1275 }\r
1276 \r
1277 /**\r
1278  * \brief Return write protect status.\r
1279  *\r
1280  * \retval 0 Protection disabled.\r
1281  * \retval 1 Protection enabled.\r
1282  */\r
1283 uint32_t pmc_get_writeprotect_status(void)\r
1284 {\r
1285         return PMC->PMC_WPMR & PMC_WPMR_WPEN;\r
1286 }\r
1287 \r
1288 /// @cond 0\r
1289 /**INDENT-OFF**/\r
1290 #ifdef __cplusplus\r
1291 }\r
1292 #endif\r
1293 /**INDENT-ON**/\r
1294 /// @endcond\r