]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_ATSAM3X_Atmel_Studio/src/asf/sam/drivers/pmc/pmc.c
Add SAM3X-EK demo.
[freertos] / FreeRTOS / Demo / CORTEX_ATSAM3X_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-2012 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 #endif\r
55 \r
56 /// @cond 0\r
57 /**INDENT-OFF**/\r
58 #ifdef __cplusplus\r
59 extern "C" {\r
60 #endif\r
61 /**INDENT-ON**/\r
62 /// @endcond\r
63 \r
64 /**\r
65  * \defgroup sam_drivers_pmc_group Power Management Controller (PMC)\r
66  *\r
67  * \par Purpose\r
68  *\r
69  * The Power Management Controller (PMC) optimizes power consumption by controlling\r
70  * all system and user peripheral clocks. The PMC enables/disables the clock inputs\r
71  * to many of the peripherals and the Cortex-M Processor.\r
72  *\r
73  * @{\r
74  */\r
75 \r
76 /**\r
77  * \brief Set the prescaler of the MCK.\r
78  *\r
79  * \param ul_pres Prescaler value.\r
80  */\r
81 void pmc_mck_set_prescaler(uint32_t ul_pres)\r
82 {\r
83         PMC->PMC_MCKR =\r
84                         (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;\r
85         while (!(PMC->PMC_SR & PMC_SR_MCKRDY));\r
86 }\r
87 \r
88 /**\r
89  * \brief Set the source of the MCK.\r
90  *\r
91  * \param ul_source Source selection value.\r
92  */\r
93 void pmc_mck_set_source(uint32_t ul_source)\r
94 {\r
95         PMC->PMC_MCKR =\r
96                         (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | ul_source;\r
97         while (!(PMC->PMC_SR & PMC_SR_MCKRDY));\r
98 }\r
99 \r
100 /**\r
101  * \brief Switch master clock source selection to slow clock.\r
102  *\r
103  * \param ul_pres Processor clock prescaler.\r
104  *\r
105  * \retval 0 Success.\r
106  * \retval 1 Timeout error.\r
107  */\r
108 uint32_t pmc_switch_mck_to_sclk(uint32_t ul_pres)\r
109 {\r
110         uint32_t ul_timeout;\r
111 \r
112         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | PMC_MCKR_CSS_SLOW_CLK;\r
113         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY); --ul_timeout) {\r
114                 if (ul_timeout == 0) {\r
115                         return 1;\r
116                 }\r
117         }\r
118 \r
119         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;\r
120         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY); --ul_timeout) {\r
121                 if (ul_timeout == 0) {\r
122                         return 1;\r
123                 }\r
124         }\r
125 \r
126         return 0;\r
127 }\r
128 \r
129 /**\r
130  * \brief Switch master clock source selection to main clock.\r
131  *\r
132  * \param ul_pres Processor clock prescaler.\r
133  *\r
134  * \retval 0 Success.\r
135  * \retval 1 Timeout error.\r
136  */\r
137 uint32_t pmc_switch_mck_to_mainck(uint32_t ul_pres)\r
138 {\r
139         uint32_t ul_timeout;\r
140 \r
141         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |\r
142                         PMC_MCKR_CSS_MAIN_CLK;\r
143         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
144                         --ul_timeout) {\r
145                 if (ul_timeout == 0) {\r
146                         return 1;\r
147                 }\r
148         }\r
149 \r
150         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;\r
151         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
152                         --ul_timeout) {\r
153                 if (ul_timeout == 0) {\r
154                         return 1;\r
155                 }\r
156         }\r
157 \r
158         return 0;\r
159 }\r
160 \r
161 /**\r
162  * \brief Switch master clock source selection to PLLA clock.\r
163  *\r
164  * \param ul_pres Processor clock prescaler.\r
165  *\r
166  * \retval 0 Success.\r
167  * \retval 1 Timeout error.\r
168  */\r
169 uint32_t pmc_switch_mck_to_pllack(uint32_t ul_pres)\r
170 {\r
171         uint32_t ul_timeout;\r
172 \r
173         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;\r
174         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
175                         --ul_timeout) {\r
176                 if (ul_timeout == 0) {\r
177                         return 1;\r
178                 }\r
179         }\r
180 \r
181         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |\r
182                         PMC_MCKR_CSS_PLLA_CLK;\r
183 \r
184         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
185                         --ul_timeout) {\r
186                 if (ul_timeout == 0) {\r
187                         return 1;\r
188                 }\r
189         }\r
190 \r
191         return 0;\r
192 }\r
193 \r
194 #if (SAM3S || SAM4S)\r
195 /**\r
196  * \brief Switch master clock source selection to PLLB clock.\r
197  *\r
198  * \param ul_pres Processor clock prescaler.\r
199  *\r
200  * \retval 0 Success.\r
201  * \retval 1 Timeout error.\r
202  */\r
203 uint32_t pmc_switch_mck_to_pllbck(uint32_t ul_pres)\r
204 {\r
205         uint32_t ul_timeout;\r
206 \r
207         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;\r
208         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
209                         --ul_timeout) {\r
210                 if (ul_timeout == 0) {\r
211                         return 1;\r
212                 }\r
213         }\r
214 \r
215         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |\r
216                         PMC_MCKR_CSS_PLLB_CLK;\r
217         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
218                         --ul_timeout) {\r
219                 if (ul_timeout == 0) {\r
220                         return 1;\r
221                 }\r
222         }\r
223 \r
224         return 0;\r
225 }\r
226 #endif\r
227 \r
228 #if (SAM3XA || SAM3U)\r
229 /**\r
230  * \brief Switch master clock source selection to UPLL clock.\r
231  *\r
232  * \param ul_pres Processor clock prescaler.\r
233  *\r
234  * \retval 0 Success.\r
235  * \retval 1 Timeout error.\r
236  */\r
237 uint32_t pmc_switch_mck_to_upllck(uint32_t ul_pres)\r
238 {\r
239         uint32_t ul_timeout;\r
240 \r
241         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;\r
242         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
243                         --ul_timeout) {\r
244                 if (ul_timeout == 0) {\r
245                         return 1;\r
246                 }\r
247         }\r
248 \r
249         PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |\r
250                         PMC_MCKR_CSS_UPLL_CLK;\r
251         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);\r
252                         --ul_timeout) {\r
253                 if (ul_timeout == 0) {\r
254                         return 1;\r
255                 }\r
256         }\r
257 \r
258         return 0;\r
259 }\r
260 #endif\r
261 \r
262 /**\r
263  * \brief Switch slow clock source selection to external 32k (Xtal or Bypass).\r
264  *\r
265  * \note This function disables the PLLs.\r
266  *\r
267  * \note Switching SCLK back to 32krc is only possible by shutting down the VDDIO\r
268  * power supply.\r
269  *\r
270  * \param ul_bypass 0 for Xtal, 1 for bypass.\r
271  */\r
272 void pmc_switch_sclk_to_32kxtal(uint32_t ul_bypass)\r
273 {\r
274         /* Set Bypass mode if required */\r
275         if (ul_bypass == 1) {\r
276                 SUPC->SUPC_MR |= SUPC_MR_KEY(SUPC_KEY_VALUE) |\r
277                                 SUPC_MR_OSCBYPASS;\r
278         }\r
279 \r
280         SUPC->SUPC_CR |= SUPC_CR_KEY(SUPC_KEY_VALUE) | SUPC_CR_XTALSEL;\r
281 }\r
282 \r
283 /**\r
284  * \brief Check if the external 32k Xtal is ready.\r
285  *\r
286  * \retval 1 External 32k Xtal is ready.\r
287  * \retval 0 External 32k Xtal is not ready.\r
288  */\r
289 uint32_t pmc_osc_is_ready_32kxtal(void)\r
290 {\r
291         return ((SUPC->SUPC_SR & SUPC_SR_OSCSEL)\r
292                         && (PMC->PMC_SR & PMC_SR_OSCSELS));\r
293 }\r
294 \r
295 /**\r
296  * \brief Switch main clock source selection to internal fast RC.\r
297  *\r
298  * \param ul_moscrcf Fast RC oscillator(4/8/12Mhz).\r
299  *\r
300  * \retval 0 Success.\r
301  * \retval 1 Timeout error.\r
302  * \retval 2 Invalid frequency.\r
303  */\r
304 void pmc_switch_mainck_to_fastrc(uint32_t ul_moscrcf)\r
305 {\r
306         uint32_t ul_needXTEN = 0;\r
307 \r
308         /* Enable Fast RC oscillator but DO NOT switch to RC now */\r
309         if (PMC->CKGR_MOR & CKGR_MOR_MOSCXTEN) {\r
310                 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCF_Msk) |\r
311                                 PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCRCEN |\r
312                                 ul_moscrcf;\r
313         } else {\r
314                 ul_needXTEN = 1;\r
315                 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCF_Msk) |\r
316                                 PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCRCEN |\r
317                                 CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCXTST(PMC_XTAL_STARTUP_TIME) |\r
318                                 ul_moscrcf;\r
319         }\r
320 \r
321         /* Wait the Fast RC to stabilize */\r
322         while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));\r
323 \r
324         /* Switch to Fast RC */\r
325         PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) | PMC_CKGR_MOR_KEY_VALUE;\r
326 \r
327         /* Disable xtal oscillator */\r
328         if (ul_needXTEN) {\r
329                 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |\r
330                                 PMC_CKGR_MOR_KEY_VALUE;\r
331         }\r
332 }\r
333 \r
334 /**\r
335  * \brief Enable fast RC oscillator.\r
336  *\r
337  * \param ul_rc Fast RC oscillator(4/8/12Mhz).\r
338  */\r
339 void pmc_osc_enable_fastrc(uint32_t ul_rc)\r
340 {\r
341         /* Enable Fast RC oscillator but DO NOT switch to RC now. Keep MOSCSEL to 1 */\r
342         PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCSEL |\r
343                         CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCRCEN | ul_rc;\r
344         /* Wait the Fast RC to stabilize */\r
345         while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));\r
346 }\r
347 \r
348 /**\r
349  * \brief Disable the internal fast RC.\r
350  */\r
351 void pmc_osc_disable_fastrc(void)\r
352 {\r
353         /* Disable Fast RC oscillator */\r
354         PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCEN & ~CKGR_MOR_MOSCRCF_Msk)\r
355                                         | PMC_CKGR_MOR_KEY_VALUE;\r
356 }\r
357 \r
358 /**\r
359  * \brief Switch main clock source selection to external Xtal/Bypass.\r
360  * The function may switch MCK to SCLK if MCK source is MAINCK to avoid any\r
361  * system crash.\r
362  *\r
363  * \note If used in Xtal mode, the Xtal is automatically enabled.\r
364  *\r
365  * \param ul_bypass 0 for Xtal, 1 for bypass.\r
366  *\r
367  * \retval 0 Success.\r
368  * \retval 1 Timeout error.\r
369  */\r
370 void pmc_switch_mainck_to_xtal(uint32_t ul_bypass)\r
371 {\r
372         /* Enable Main Xtal oscillator */\r
373         if (ul_bypass) {\r
374                 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |\r
375                                 PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCXTBY |\r
376                                 CKGR_MOR_MOSCSEL;\r
377         } else {\r
378                 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) |\r
379                                 PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCXTEN |\r
380                                 CKGR_MOR_MOSCXTST(PMC_XTAL_STARTUP_TIME);\r
381                 /* Wait the Xtal to stabilize */\r
382                 while (!(PMC->PMC_SR & PMC_SR_MOSCXTS));\r
383 \r
384                 PMC->CKGR_MOR |= PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCSEL;\r
385         }\r
386 }\r
387 \r
388 /**\r
389  * \brief Disable the external Xtal.\r
390  *\r
391  * \param ul_bypass 0 for Xtal, 1 for bypass.\r
392  */\r
393 void pmc_osc_disable_xtal(uint32_t ul_bypass)\r
394 {\r
395         /* Disable xtal oscillator */\r
396         if (ul_bypass) {\r
397                 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) |\r
398                                 PMC_CKGR_MOR_KEY_VALUE;\r
399         } else {\r
400                 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |\r
401                                 PMC_CKGR_MOR_KEY_VALUE;\r
402         }\r
403 }\r
404 \r
405 /**\r
406  * \brief Check if the MAINCK is ready. Depending on MOSCEL, MAINCK can be one\r
407  * of Xtal, bypass or internal RC.\r
408  *\r
409  * \retval 1 Xtal is ready.\r
410  * \retval 0 Xtal is not ready.\r
411  */\r
412 uint32_t pmc_osc_is_ready_mainck(void)\r
413 {\r
414         return PMC->PMC_SR & PMC_SR_MOSCSELS;\r
415 }\r
416 \r
417 /**\r
418  * \brief Enable PLLA clock.\r
419  *\r
420  * \param mula PLLA multiplier.\r
421  * \param pllacount PLLA counter.\r
422  * \param diva Divider.\r
423  */\r
424 void pmc_enable_pllack(uint32_t mula, uint32_t pllacount, uint32_t diva)\r
425 {\r
426         /* first disable the PLL to unlock the lock!*/\r
427         pmc_disable_pllack();\r
428 \r
429         PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_DIVA(diva) |\r
430                         CKGR_PLLAR_PLLACOUNT(pllacount) | CKGR_PLLAR_MULA(mula);\r
431         while ((PMC->PMC_SR & PMC_SR_LOCKA) == 0);\r
432 }\r
433 \r
434 /**\r
435  * \brief Disable PLLA clock.\r
436  */\r
437 void pmc_disable_pllack(void)\r
438 {\r
439         PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0);\r
440 }\r
441 \r
442 /**\r
443  * \brief Is PLLA locked?\r
444  *\r
445  * \retval 0 Not locked.\r
446  * \retval 1 Locked.\r
447  */\r
448 uint32_t pmc_is_locked_pllack(void)\r
449 {\r
450         return (PMC->PMC_SR & PMC_SR_LOCKA);\r
451 }\r
452 \r
453 #if (SAM3S || SAM4S)\r
454 /**\r
455  * \brief Enable PLLB clock.\r
456  *\r
457  * \param mulb PLLB multiplier.\r
458  * \param pllbcount PLLB counter.\r
459  * \param divb Divider.\r
460  */\r
461 void pmc_enable_pllbck(uint32_t mulb, uint32_t pllbcount, uint32_t divb)\r
462 {\r
463         /* first disable the PLL to unlock the lock!*/\r
464         pmc_disable_pllbck();\r
465 \r
466         PMC->CKGR_PLLBR =\r
467                         CKGR_PLLBR_DIVB(divb) | CKGR_PLLBR_PLLBCOUNT(pllbcount)\r
468                         | CKGR_PLLBR_MULB(mulb);\r
469         while ((PMC->PMC_SR & PMC_SR_LOCKB) == 0);\r
470 }\r
471 \r
472 /**\r
473  * \brief Disable PLLB clock.\r
474  */\r
475 void pmc_disable_pllbck(void)\r
476 {\r
477         PMC->CKGR_PLLBR = CKGR_PLLBR_MULB(0);\r
478 }\r
479 \r
480 /**\r
481  * \brief Is PLLB locked?\r
482  *\r
483  * \retval 0 Not locked.\r
484  * \retval 1 Locked.\r
485  */\r
486 uint32_t pmc_is_locked_pllbck(void)\r
487 {\r
488         return (PMC->PMC_SR & PMC_SR_LOCKB);\r
489 }\r
490 #endif\r
491 \r
492 #if (SAM3XA || SAM3U)\r
493 /**\r
494  * \brief Enable UPLL clock.\r
495  */\r
496 void pmc_enable_upll_clock(void)\r
497 {\r
498         PMC->CKGR_UCKR = CKGR_UCKR_UPLLCOUNT(3) | CKGR_UCKR_UPLLEN;\r
499 \r
500         /* Wait UTMI PLL Lock Status */\r
501         while (!(PMC->PMC_SR & PMC_SR_LOCKU));\r
502 }\r
503 \r
504 /**\r
505  * \brief Disable UPLL clock.\r
506  */\r
507 void pmc_disable_upll_clock(void)\r
508 {\r
509         PMC->CKGR_UCKR &= ~CKGR_UCKR_UPLLEN;\r
510 }\r
511 \r
512 /**\r
513  * \brief Is UPLL locked?\r
514  *\r
515  * \retval 0 Not locked.\r
516  * \retval 1 Locked.\r
517  */\r
518 uint32_t pmc_is_locked_upll(void)\r
519 {\r
520         return (PMC->PMC_SR & PMC_SR_LOCKU);\r
521 }\r
522 #endif\r
523 \r
524 /**\r
525  * \brief Enable the specified peripheral clock.\r
526  *\r
527  * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).\r
528  *\r
529  * \param ul_id Peripheral ID (ID_xxx).\r
530  *\r
531  * \retval 0 Success.\r
532  * \retval 1 Invalid parameter.\r
533  */\r
534 uint32_t pmc_enable_periph_clk(uint32_t ul_id)\r
535 {\r
536         if (ul_id > MAX_PERIPH_ID) {\r
537                 return 1;\r
538         }\r
539 \r
540         if (ul_id < 32) {\r
541                 if ((PMC->PMC_PCSR0 & (1u << ul_id)) != (1u << ul_id)) {\r
542                         PMC->PMC_PCER0 = 1 << ul_id;\r
543                 }\r
544 #if (SAM3S || SAM3XA || SAM4S)\r
545         } else {\r
546                 ul_id -= 32;\r
547                 if ((PMC->PMC_PCSR1 & (1u << ul_id)) != (1u << ul_id)) {\r
548                         PMC->PMC_PCER1 = 1 << ul_id;\r
549                 }\r
550 #endif\r
551         }\r
552 \r
553         return 0;\r
554 }\r
555 \r
556 /**\r
557  * \brief Disable the specified peripheral clock.\r
558  *\r
559  * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).\r
560  *\r
561  * \param ul_id Peripheral ID (ID_xxx).\r
562  *\r
563  * \retval 0 Success.\r
564  * \retval 1 Invalid parameter.\r
565  */\r
566 uint32_t pmc_disable_periph_clk(uint32_t ul_id)\r
567 {\r
568         if (ul_id > MAX_PERIPH_ID) {\r
569                 return 1;\r
570         }\r
571 \r
572         if (ul_id < 32) {\r
573                 if ((PMC->PMC_PCSR0 & (1u << ul_id)) == (1u << ul_id)) {\r
574                         PMC->PMC_PCDR0 = 1 << ul_id;\r
575                 }\r
576 #if (SAM3S || SAM3XA || SAM4S)\r
577         } else {\r
578                 ul_id -= 32;\r
579                 if ((PMC->PMC_PCSR1 & (1u << ul_id)) == (1u << ul_id)) {\r
580                         PMC->PMC_PCDR1 = 1 << ul_id;\r
581                 }\r
582 #endif\r
583         }\r
584         return 0;\r
585 }\r
586 \r
587 /**\r
588  * \brief Enable all peripheral clocks.\r
589  */\r
590 void pmc_enable_all_periph_clk(void)\r
591 {\r
592         PMC->PMC_PCER0 = PMC_MASK_STATUS0;\r
593         while ((PMC->PMC_PCSR0 & PMC_MASK_STATUS0) != PMC_MASK_STATUS0);\r
594 \r
595 #if (SAM3S || SAM3XA || SAM4S)\r
596         PMC->PMC_PCER1 = PMC_MASK_STATUS1;\r
597         while ((PMC->PMC_PCSR1 & PMC_MASK_STATUS1) != PMC_MASK_STATUS1);\r
598 #endif\r
599 }\r
600 \r
601 /**\r
602  * \brief Disable all peripheral clocks.\r
603  */\r
604 void pmc_disable_all_periph_clk(void)\r
605 {\r
606         PMC->PMC_PCDR0 = PMC_MASK_STATUS0;\r
607         while ((PMC->PMC_PCSR0 & PMC_MASK_STATUS0) != 0);\r
608 \r
609 #if (SAM3S || SAM3XA || SAM4S)\r
610         PMC->PMC_PCDR1 = PMC_MASK_STATUS1;\r
611         while ((PMC->PMC_PCSR1 & PMC_MASK_STATUS1) != 0);\r
612 #endif\r
613 }\r
614 \r
615 /**\r
616  * \brief Check if the specified peripheral clock is enabled.\r
617  *\r
618  * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).\r
619  *\r
620  * \param ul_id Peripheral ID (ID_xxx).\r
621  *\r
622  * \retval 0 Peripheral clock is disabled or unknown.\r
623  * \retval 1 Peripheral clock is enabled.\r
624  */\r
625 uint32_t pmc_is_periph_clk_enabled(uint32_t ul_id)\r
626 {\r
627         if (ul_id > MAX_PERIPH_ID) {\r
628                 return 0;\r
629         }\r
630 \r
631 #if (SAM3S || SAM3XA || SAM4S)\r
632         if (ul_id < 32) {\r
633 #endif\r
634                 if ((PMC->PMC_PCSR0 & (1u << ul_id))) {\r
635                         return 1;\r
636                 } else {\r
637                         return 0;\r
638                 }\r
639 #if (SAM3S || SAM3XA || SAM4S)\r
640         } else {\r
641                 ul_id -= 32;\r
642                 if ((PMC->PMC_PCSR1 & (1u << ul_id))) {\r
643                         return 1;\r
644                 } else {\r
645                         return 0;\r
646                 }\r
647         }\r
648 #endif\r
649 }\r
650 \r
651 /**\r
652  * \brief Set the prescaler for the specified programmable clock.\r
653  *\r
654  * \param ul_id Peripheral ID.\r
655  * \param ul_pres Prescaler value.\r
656  */\r
657 void pmc_pck_set_prescaler(uint32_t ul_id, uint32_t ul_pres)\r
658 {\r
659         PMC->PMC_PCK[ul_id] =\r
660                         (PMC->PMC_PCK[ul_id] & ~PMC_PCK_PRES_Msk) | ul_pres;\r
661         while ((PMC->PMC_SCER & (PMC_SCER_PCK0 << ul_id))\r
662                         && !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)));\r
663 }\r
664 \r
665 /**\r
666  * \brief Set the source oscillator for the specified programmable clock.\r
667  *\r
668  * \param ul_id Peripheral ID.\r
669  * \param ul_source Source selection value.\r
670  */\r
671 void pmc_pck_set_source(uint32_t ul_id, uint32_t ul_source)\r
672 {\r
673         PMC->PMC_PCK[ul_id] =\r
674                         (PMC->PMC_PCK[ul_id] & ~PMC_PCK_CSS_Msk) | ul_source;\r
675         while ((PMC->PMC_SCER & (PMC_SCER_PCK0 << ul_id))\r
676                         && !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)));\r
677 }\r
678 \r
679 /**\r
680  * \brief Switch programmable clock source selection to slow clock.\r
681  *\r
682  * \param ul_id Id of the programmable clock.\r
683  * \param ul_pres Programmable clock prescaler.\r
684  *\r
685  * \retval 0 Success.\r
686  * \retval 1 Timeout error.\r
687  */\r
688 uint32_t pmc_switch_pck_to_sclk(uint32_t ul_id, uint32_t ul_pres)\r
689 {\r
690         uint32_t ul_timeout;\r
691 \r
692         PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_SLOW_CLK | ul_pres;\r
693         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id));\r
694                         --ul_timeout) {\r
695                 if (ul_timeout == 0) {\r
696                         return 1;\r
697                 }\r
698         }\r
699 \r
700         return 0;\r
701 }\r
702 \r
703 /**\r
704  * \brief Switch programmable clock source selection to main clock.\r
705  *\r
706  * \param ul_id Id of the programmable clock.\r
707  * \param ul_pres Programmable clock prescaler.\r
708  *\r
709  * \retval 0 Success.\r
710  * \retval 1 Timeout error.\r
711  */\r
712 uint32_t pmc_switch_pck_to_mainck(uint32_t ul_id, uint32_t ul_pres)\r
713 {\r
714         uint32_t ul_timeout;\r
715 \r
716         PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_MAIN_CLK | ul_pres;\r
717         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id));\r
718                         --ul_timeout) {\r
719                 if (ul_timeout == 0) {\r
720                         return 1;\r
721                 }\r
722         }\r
723 \r
724         return 0;\r
725 }\r
726 \r
727 /**\r
728  * \brief Switch programmable clock source selection to PLLA clock.\r
729  *\r
730  * \param ul_id Id of the programmable clock.\r
731  * \param ul_pres Programmable clock prescaler.\r
732  *\r
733  * \retval 0 Success.\r
734  * \retval 1 Timeout error.\r
735  */\r
736 uint32_t pmc_switch_pck_to_pllack(uint32_t ul_id, uint32_t ul_pres)\r
737 {\r
738         uint32_t ul_timeout;\r
739 \r
740         PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_PLLA_CLK | ul_pres;\r
741         for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id));\r
742                         --ul_timeout) {\r
743                 if (ul_timeout == 0) {\r
744                         return 1;\r
745                 }\r
746         }\r
747 \r
748         return 0;\r
749 }\r
750 \r
751 #if (SAM3S || SAM4S)\r
752 /**\r
753  * \brief Switch programmable clock source selection to PLLB clock.\r
754  *\r
755  * \param ul_id Id of the programmable clock.\r
756  * \param ul_pres Programmable clock prescaler.\r
757  *\r
758  * \retval 0 Success.\r
759  * \retval 1 Timeout error.\r
760  */\r
761 uint32_t pmc_switch_pck_to_pllbck(uint32_t ul_id, uint32_t ul_pres)\r
762 {\r
763         uint32_t ul_timeout;\r
764 \r
765         PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_PLLB_CLK | ul_pres;\r
766         for (ul_timeout = PMC_TIMEOUT;\r
767                         !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id));\r
768                         --ul_timeout) {\r
769                 if (ul_timeout == 0) {\r
770                         return 1;\r
771                 }\r
772         }\r
773 \r
774         return 0;\r
775 }\r
776 #endif\r
777 \r
778 #if (SAM3XA || SAM3U)\r
779 /**\r
780  * \brief Switch programmable clock source selection to UPLL clock.\r
781  *\r
782  * \param ul_id Id of the programmable clock.\r
783  * \param ul_pres Programmable clock prescaler.\r
784  *\r
785  * \retval 0 Success.\r
786  * \retval 1 Timeout error.\r
787  */\r
788 uint32_t pmc_switch_pck_to_upllck(uint32_t ul_id, uint32_t ul_pres)\r
789 {\r
790         uint32_t ul_timeout;\r
791 \r
792         PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_UPLL_CLK | ul_pres;\r
793         for (ul_timeout = PMC_TIMEOUT;\r
794                         !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id));\r
795                         --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 #endif\r
804 \r
805 /**\r
806  * \brief Enable the specified programmable clock.\r
807  *\r
808  * \param ul_id Id of the programmable clock.\r
809  */\r
810 void pmc_enable_pck(uint32_t ul_id)\r
811 {\r
812         PMC->PMC_SCER = PMC_SCER_PCK0 << ul_id;\r
813 }\r
814 \r
815 /**\r
816  * \brief Disable the specified programmable clock.\r
817  *\r
818  * \param ul_id Id of the programmable clock.\r
819  */\r
820 void pmc_disable_pck(uint32_t ul_id)\r
821 {\r
822         PMC->PMC_SCDR = PMC_SCER_PCK0 << ul_id;\r
823 }\r
824 \r
825 /**\r
826  * \brief Enable all programmable clocks.\r
827  */\r
828 void pmc_enable_all_pck(void)\r
829 {\r
830         PMC->PMC_SCER = PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2;\r
831 }\r
832 \r
833 /**\r
834  * \brief Disable all programmable clocks.\r
835  */\r
836 void pmc_disable_all_pck(void)\r
837 {\r
838         PMC->PMC_SCDR = PMC_SCDR_PCK0 | PMC_SCDR_PCK1 | PMC_SCDR_PCK2;\r
839 }\r
840 \r
841 /**\r
842  * \brief Check if the specified programmable clock is enabled.\r
843  *\r
844  * \param ul_id Id of the programmable clock.\r
845  *\r
846  * \retval 0 Programmable clock is disabled or unknown.\r
847  * \retval 1 Programmable clock is enabled.\r
848  */\r
849 uint32_t pmc_is_pck_enabled(uint32_t ul_id)\r
850 {\r
851         if (ul_id > 2) {\r
852                 return 0;\r
853         }\r
854 \r
855         return (PMC->PMC_SCSR & (PMC_SCSR_PCK0 << ul_id));\r
856 }\r
857 \r
858 #if (SAM3S || SAM3XA || SAM4S)\r
859 /**\r
860  * \brief Switch UDP (USB) clock source selection to PLLA clock.\r
861  *\r
862  * \param ul_usbdiv Clock divisor.\r
863  */\r
864 void pmc_switch_udpck_to_pllack(uint32_t ul_usbdiv)\r
865 {\r
866         PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv);\r
867 }\r
868 #endif\r
869 \r
870 #if (SAM3S || SAM4S)\r
871 /**\r
872  * \brief Switch UDP (USB) clock source selection to PLLB clock.\r
873  *\r
874  * \param ul_usbdiv Clock divisor.\r
875  */\r
876 void pmc_switch_udpck_to_pllbck(uint32_t ul_usbdiv)\r
877 {\r
878         PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv) | PMC_USB_USBS;\r
879 }\r
880 #endif\r
881 \r
882 #if (SAM3XA)\r
883 /**\r
884  * \brief Switch UDP (USB) clock source selection to UPLL clock.\r
885  *\r
886  * \param dw_usbdiv Clock divisor.\r
887  */\r
888 void pmc_switch_udpck_to_upllck(uint32_t ul_usbdiv)\r
889 {\r
890         PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(ul_usbdiv);\r
891 }\r
892 #endif\r
893 \r
894 #if (SAM3S || SAM3XA || SAM4S)\r
895 /**\r
896  * \brief Enable UDP (USB) clock.\r
897  */\r
898 void pmc_enable_udpck(void)\r
899 {\r
900 # if (SAM3S || SAM4S)\r
901         PMC->PMC_SCER = PMC_SCER_UDP;\r
902 # else\r
903         PMC->PMC_SCER = PMC_SCER_UOTGCLK;\r
904 # endif\r
905 }\r
906 \r
907 /**\r
908  * \brief Disable UDP (USB) clock.\r
909  */\r
910 void pmc_disable_udpck(void)\r
911 {\r
912 # if (SAM3S || SAM4S)\r
913         PMC->PMC_SCDR = PMC_SCDR_UDP;\r
914 # else\r
915         PMC->PMC_SCDR = PMC_SCDR_UOTGCLK;\r
916 # endif\r
917 }\r
918 #endif\r
919 \r
920 /**\r
921  * \brief Enable PMC interrupts.\r
922  *\r
923  * \param ul_sources Interrupt sources bit map.\r
924  */\r
925 void pmc_enable_interrupt(uint32_t ul_sources)\r
926 {\r
927         PMC->PMC_IER = ul_sources;\r
928 }\r
929 \r
930 /**\r
931  * \brief Disable PMC interrupts.\r
932  *\r
933  * \param ul_sources Interrupt sources bit map.\r
934  */\r
935 void pmc_disable_interrupt(uint32_t ul_sources)\r
936 {\r
937         PMC->PMC_IDR = ul_sources;\r
938 }\r
939 \r
940 /**\r
941  * \brief Get PMC interrupt mask.\r
942  *\r
943  * \return The interrupt mask value.\r
944  */\r
945 uint32_t pmc_get_interrupt_mask(void)\r
946 {\r
947         return PMC->PMC_IMR;\r
948 }\r
949 \r
950 /**\r
951  * \brief Get current status.\r
952  *\r
953  * \return The current PMC status.\r
954  */\r
955 uint32_t pmc_get_status(void)\r
956 {\r
957         return PMC->PMC_SR;\r
958 }\r
959 \r
960 /**\r
961  * \brief Set the wake-up inputs for fast startup mode registers (event generation).\r
962  *\r
963  * \param ul_inputs Wake up inputs to enable.\r
964  */\r
965 void pmc_set_fast_startup_input(uint32_t ul_inputs)\r
966 {\r
967         ul_inputs &= PMC_FAST_STARTUP_Msk;\r
968         PMC->PMC_FSMR |= ul_inputs;\r
969 }\r
970 \r
971 /**\r
972  * \brief Clear the wake-up inputs for fast startup mode registers (remove event generation).\r
973  *\r
974  * \param ul_inputs Wake up inputs to disable.\r
975  */\r
976 void pmc_clr_fast_startup_input(uint32_t ul_inputs)\r
977 {\r
978         ul_inputs &= PMC_FAST_STARTUP_Msk;\r
979         PMC->PMC_FSMR &= ~ul_inputs;\r
980 }\r
981 \r
982 /**\r
983  * \brief Enable Sleep Mode.\r
984  * Enter condition: (WFE or WFI) + (SLEEPDEEP bit = 0) + (LPM bit = 0)\r
985  *\r
986  * \param uc_type 0 for wait for interrupt, 1 for wait for event.\r
987  */\r
988 void pmc_enable_sleepmode(uint8_t uc_type)\r
989 {\r
990         PMC->PMC_FSMR &= (uint32_t) ~ PMC_FSMR_LPM; // Enter Sleep mode\r
991         SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk; // Deep sleep\r
992 \r
993         if (uc_type == 0) {\r
994                 __WFI();\r
995         } else {\r
996                 __WFE();\r
997         }\r
998 }\r
999 \r
1000 /**\r
1001  * \brief Enable Wait Mode.\r
1002  * Enter condition: WFE + (SLEEPDEEP bit = 0) + (LPM bit = 1)\r
1003  */\r
1004 void pmc_enable_waitmode(void)\r
1005 {\r
1006         uint32_t i;\r
1007 \r
1008         PMC->PMC_FSMR |= PMC_FSMR_LPM; // Enter Wait mode\r
1009         SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk; // Deep sleep\r
1010         __WFE();\r
1011 \r
1012         /* Waiting for MOSCRCEN bit cleared is strongly recommended\r
1013          * to ensure that the core will not execute undesired instructions\r
1014          */\r
1015         for (i = 0; i < 500; i++) {\r
1016                 __NOP();\r
1017         }\r
1018         while (!(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN));\r
1019 }\r
1020 \r
1021 /**\r
1022  * \brief Enable Backup Mode.\r
1023  * Enter condition: WFE + (SLEEPDEEP bit = 1)\r
1024  */\r
1025 void pmc_enable_backupmode(void)\r
1026 {\r
1027         SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;\r
1028         __WFE();\r
1029 }\r
1030 \r
1031 /**\r
1032  * \brief Enable Clock Failure Detector.\r
1033  */\r
1034 void pmc_enable_clock_failure_detector(void)\r
1035 {\r
1036         uint32_t ul_reg = PMC->CKGR_MOR;\r
1037 \r
1038         PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_CFDEN | ul_reg;\r
1039 }\r
1040 \r
1041 /**\r
1042  * \brief Disable Clock Failure Detector.\r
1043  */\r
1044 void pmc_disable_clock_failure_detector(void)\r
1045 {\r
1046         uint32_t ul_reg = PMC->CKGR_MOR & (~CKGR_MOR_CFDEN);\r
1047 \r
1048         PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | ul_reg;\r
1049 }\r
1050 \r
1051 /**\r
1052  * \brief Enable or disable write protect of PMC registers.\r
1053  *\r
1054  * \param ul_enable 1 to enable, 0 to disable.\r
1055  */\r
1056 void pmc_set_writeprotect(uint32_t ul_enable)\r
1057 {\r
1058         if (ul_enable) {\r
1059                 PMC->PMC_WPMR = PMC_WPMR_WPKEY_VALUE | PMC_WPMR_WPEN;\r
1060         } else {\r
1061                 PMC->PMC_WPMR = PMC_WPMR_WPKEY_VALUE;\r
1062         }\r
1063 }\r
1064 \r
1065 /**\r
1066  * \brief Return write protect status.\r
1067  *\r
1068  * \retval 0 Protection disabled.\r
1069  * \retval 1 Protection enabled.\r
1070  */\r
1071 uint32_t pmc_get_writeprotect_status(void)\r
1072 {\r
1073         return PMC->PMC_WPMR & PMC_WPMR_WPEN;\r
1074 }\r
1075 \r
1076 /// @cond 0\r
1077 /**INDENT-OFF**/\r
1078 #ifdef __cplusplus\r
1079 }\r
1080 #endif\r
1081 /**INDENT-ON**/\r
1082 /// @endcond\r