4 * \brief Power Management Controller (PMC) driver for SAM.
\r
6 * Copyright (c) 2011 - 2013 Atmel Corporation. All rights reserved.
\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
15 * 1. Redistributions of source code must retain the above copyright notice,
\r
16 * this list of conditions and the following disclaimer.
\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
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
25 * 4. This software may only be redistributed and used in connection with an
\r
26 * Atmel microcontroller product.
\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
47 # define MAX_PERIPH_ID 31
\r
49 # define MAX_PERIPH_ID 44
\r
51 # define MAX_PERIPH_ID 29
\r
52 #elif (SAM3S || SAM4S)
\r
53 # define MAX_PERIPH_ID 34
\r
55 # define MAX_PERIPH_ID 47
\r
57 # define MAX_PERIPH_ID 31
\r
69 * \defgroup sam_drivers_pmc_group Power Management Controller (PMC)
\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
81 * \brief Set the prescaler of the MCK.
\r
83 * \param ul_pres Prescaler value.
\r
85 void pmc_mck_set_prescaler(uint32_t ul_pres)
\r
88 (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;
\r
89 while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
\r
93 * \brief Set the source of the MCK.
\r
95 * \param ul_source Source selection value.
\r
97 void pmc_mck_set_source(uint32_t ul_source)
\r
100 (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | ul_source;
\r
101 while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
\r
105 * \brief Switch master clock source selection to slow clock.
\r
107 * \param ul_pres Processor clock prescaler.
\r
109 * \retval 0 Success.
\r
110 * \retval 1 Timeout error.
\r
112 uint32_t pmc_switch_mck_to_sclk(uint32_t ul_pres)
\r
114 uint32_t ul_timeout;
\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
120 if (ul_timeout == 0) {
\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
128 if (ul_timeout == 0) {
\r
137 * \brief Switch master clock source selection to main clock.
\r
139 * \param ul_pres Processor clock prescaler.
\r
141 * \retval 0 Success.
\r
142 * \retval 1 Timeout error.
\r
144 uint32_t pmc_switch_mck_to_mainck(uint32_t ul_pres)
\r
146 uint32_t ul_timeout;
\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
152 if (ul_timeout == 0) {
\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
160 if (ul_timeout == 0) {
\r
169 * \brief Switch master clock source selection to PLLA clock.
\r
171 * \param ul_pres Processor clock prescaler.
\r
173 * \retval 0 Success.
\r
174 * \retval 1 Timeout error.
\r
176 uint32_t pmc_switch_mck_to_pllack(uint32_t ul_pres)
\r
178 uint32_t ul_timeout;
\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
183 if (ul_timeout == 0) {
\r
188 PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |
\r
189 PMC_MCKR_CSS_PLLA_CLK;
\r
191 for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
\r
193 if (ul_timeout == 0) {
\r
201 #if (SAM3S || SAM4S)
\r
203 * \brief Switch master clock source selection to PLLB clock.
\r
205 * \param ul_pres Processor clock prescaler.
\r
207 * \retval 0 Success.
\r
208 * \retval 1 Timeout error.
\r
210 uint32_t pmc_switch_mck_to_pllbck(uint32_t ul_pres)
\r
212 uint32_t ul_timeout;
\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
217 if (ul_timeout == 0) {
\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
226 if (ul_timeout == 0) {
\r
235 #if (SAM3XA || SAM3U)
\r
237 * \brief Switch master clock source selection to UPLL clock.
\r
239 * \param ul_pres Processor clock prescaler.
\r
241 * \retval 0 Success.
\r
242 * \retval 1 Timeout error.
\r
244 uint32_t pmc_switch_mck_to_upllck(uint32_t ul_pres)
\r
246 uint32_t ul_timeout;
\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
251 if (ul_timeout == 0) {
\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
260 if (ul_timeout == 0) {
\r
270 * \brief Switch slow clock source selection to external 32k (Xtal or Bypass).
\r
272 * \note This function disables the PLLs.
\r
274 * \note Switching SCLK back to 32krc is only possible by shutting down the
\r
275 * VDDIO power supply.
\r
277 * \param ul_bypass 0 for Xtal, 1 for bypass.
\r
279 void pmc_switch_sclk_to_32kxtal(uint32_t ul_bypass)
\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
287 SUPC->SUPC_CR = SUPC_CR_KEY(SUPC_KEY_VALUE) | SUPC_CR_XTALSEL;
\r
291 * \brief Check if the external 32k Xtal is ready.
\r
293 * \retval 1 External 32k Xtal is ready.
\r
294 * \retval 0 External 32k Xtal is not ready.
\r
296 uint32_t pmc_osc_is_ready_32kxtal(void)
\r
298 return ((SUPC->SUPC_SR & SUPC_SR_OSCSEL)
\r
299 && (PMC->PMC_SR & PMC_SR_OSCSELS));
\r
303 * \brief Switch main clock source selection to internal fast RC.
\r
305 * \param ul_moscrcf Fast RC oscillator(4/8/12Mhz).
\r
307 * \retval 0 Success.
\r
308 * \retval 1 Timeout error.
\r
309 * \retval 2 Invalid frequency.
\r
311 void pmc_switch_mainck_to_fastrc(uint32_t ul_moscrcf)
\r
313 uint32_t ul_needXTEN = 0;
\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
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
328 /* Wait the Fast RC to stabilize */
\r
329 while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));
\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
335 /* Disable xtal oscillator */
\r
337 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |
\r
338 PMC_CKGR_MOR_KEY_VALUE;
\r
343 * \brief Enable fast RC oscillator.
\r
345 * \param ul_rc Fast RC oscillator(4/8/12Mhz).
\r
347 void pmc_osc_enable_fastrc(uint32_t ul_rc)
\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
358 * \brief Disable the internal fast RC.
\r
360 void pmc_osc_disable_fastrc(void)
\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
369 * \brief Check if the main fastrc is ready.
\r
371 * \retval 0 Xtal is not ready, otherwise ready.
\r
373 uint32_t pmc_osc_is_ready_fastrc(void)
\r
375 return (PMC->PMC_SR & PMC_SR_MOSCRCS);
\r
379 * \brief Enable main XTAL oscillator.
\r
381 * \param ul_xtal_startup_time Xtal start-up time, in number of slow clocks.
\r
383 void pmc_osc_enable_main_xtal(uint32_t ul_xtal_startup_time)
\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
395 * \brief Bypass main XTAL.
\r
397 void pmc_osc_bypass_main_xtal(void)
\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
408 * \brief Disable the main Xtal.
\r
410 void pmc_osc_disable_main_xtal(void)
\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
418 * \brief Check if the main crystal is bypassed.
\r
420 * \retval 0 Xtal is bypassed, otherwise not.
\r
422 uint32_t pmc_osc_is_bypassed_main_xtal(void)
\r
424 return (PMC->CKGR_MOR & CKGR_MOR_MOSCXTBY);
\r
428 * \brief Check if the main crystal is ready.
\r
430 * \note If main crystal is bypassed, it's always ready.
\r
432 * \retval 0 main crystal is not ready, otherwise ready.
\r
434 uint32_t pmc_osc_is_ready_main_xtal(void)
\r
436 return (PMC->PMC_SR & PMC_SR_MOSCXTS);
\r
440 * \brief Switch main clock source selection to external Xtal/Bypass.
\r
442 * \note The function may switch MCK to SCLK if MCK source is MAINCK to avoid
\r
443 * any system crash.
\r
445 * \note If used in Xtal mode, the Xtal is automatically enabled.
\r
447 * \param ul_bypass 0 for Xtal, 1 for bypass.
\r
449 * \retval 0 Success.
\r
450 * \retval 1 Timeout error.
\r
452 void pmc_switch_mainck_to_xtal(uint32_t ul_bypass,
\r
453 uint32_t ul_xtal_startup_time)
\r
455 /* Enable Main Xtal oscillator */
\r
457 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |
\r
458 PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCXTBY |
\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
467 PMC->CKGR_MOR |= PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCSEL;
\r
472 * \brief Disable the external Xtal.
\r
474 * \param ul_bypass 0 for Xtal, 1 for bypass.
\r
476 void pmc_osc_disable_xtal(uint32_t ul_bypass)
\r
478 /* Disable xtal oscillator */
\r
480 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) |
\r
481 PMC_CKGR_MOR_KEY_VALUE;
\r
483 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |
\r
484 PMC_CKGR_MOR_KEY_VALUE;
\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
492 * \retval 1 Xtal is ready.
\r
493 * \retval 0 Xtal is not ready.
\r
495 uint32_t pmc_osc_is_ready_mainck(void)
\r
497 return PMC->PMC_SR & PMC_SR_MOSCSELS;
\r
501 * \brief Select Main Crystal or internal RC as main clock source.
\r
503 * \note This function will not enable/disable RC or Main Crystal.
\r
505 * \param ul_xtal_rc 0 internal RC is selected, otherwise Main Crystal.
\r
507 void pmc_mainck_osc_select(uint32_t ul_xtal_rc)
\r
509 uint32_t mor = PMC->CKGR_MOR;
\r
511 mor |= CKGR_MOR_MOSCSEL;
\r
513 mor &= ~CKGR_MOR_MOSCSEL;
\r
515 PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | mor;
\r
519 * \brief Enable PLLA clock.
\r
521 * \param mula PLLA multiplier.
\r
522 * \param pllacount PLLA counter.
\r
523 * \param diva Divider.
\r
525 void pmc_enable_pllack(uint32_t mula, uint32_t pllacount, uint32_t diva)
\r
527 /* first disable the PLL to unlock the lock */
\r
528 pmc_disable_pllack();
\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
536 * \brief Disable PLLA clock.
\r
538 void pmc_disable_pllack(void)
\r
540 PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0);
\r
544 * \brief Is PLLA locked?
\r
546 * \retval 0 Not locked.
\r
547 * \retval 1 Locked.
\r
549 uint32_t pmc_is_locked_pllack(void)
\r
551 return (PMC->PMC_SR & PMC_SR_LOCKA);
\r
554 #if (SAM3S || SAM4S)
\r
556 * \brief Enable PLLB clock.
\r
558 * \param mulb PLLB multiplier.
\r
559 * \param pllbcount PLLB counter.
\r
560 * \param divb Divider.
\r
562 void pmc_enable_pllbck(uint32_t mulb, uint32_t pllbcount, uint32_t divb)
\r
564 /* first disable the PLL to unlock the lock */
\r
565 pmc_disable_pllbck();
\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
574 * \brief Disable PLLB clock.
\r
576 void pmc_disable_pllbck(void)
\r
578 PMC->CKGR_PLLBR = CKGR_PLLBR_MULB(0);
\r
582 * \brief Is PLLB locked?
\r
584 * \retval 0 Not locked.
\r
585 * \retval 1 Locked.
\r
587 uint32_t pmc_is_locked_pllbck(void)
\r
589 return (PMC->PMC_SR & PMC_SR_LOCKB);
\r
593 #if (SAM3XA || SAM3U)
\r
595 * \brief Enable UPLL clock.
\r
597 void pmc_enable_upll_clock(void)
\r
599 PMC->CKGR_UCKR = CKGR_UCKR_UPLLCOUNT(3) | CKGR_UCKR_UPLLEN;
\r
601 /* Wait UTMI PLL Lock Status */
\r
602 while (!(PMC->PMC_SR & PMC_SR_LOCKU));
\r
606 * \brief Disable UPLL clock.
\r
608 void pmc_disable_upll_clock(void)
\r
610 PMC->CKGR_UCKR &= ~CKGR_UCKR_UPLLEN;
\r
614 * \brief Is UPLL locked?
\r
616 * \retval 0 Not locked.
\r
617 * \retval 1 Locked.
\r
619 uint32_t pmc_is_locked_upll(void)
\r
621 return (PMC->PMC_SR & PMC_SR_LOCKU);
\r
626 * \brief Enable the specified peripheral clock.
\r
628 * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
\r
630 * \param ul_id Peripheral ID (ID_xxx).
\r
632 * \retval 0 Success.
\r
633 * \retval 1 Invalid parameter.
\r
635 uint32_t pmc_enable_periph_clk(uint32_t ul_id)
\r
637 if (ul_id > MAX_PERIPH_ID) {
\r
642 if ((PMC->PMC_PCSR0 & (1u << ul_id)) != (1u << ul_id)) {
\r
643 PMC->PMC_PCER0 = 1 << ul_id;
\r
645 #if (SAM3S || SAM3XA || SAM4S || SAM4E)
\r
648 if ((PMC->PMC_PCSR1 & (1u << ul_id)) != (1u << ul_id)) {
\r
649 PMC->PMC_PCER1 = 1 << ul_id;
\r
658 * \brief Disable the specified peripheral clock.
\r
660 * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
\r
662 * \param ul_id Peripheral ID (ID_xxx).
\r
664 * \retval 0 Success.
\r
665 * \retval 1 Invalid parameter.
\r
667 uint32_t pmc_disable_periph_clk(uint32_t ul_id)
\r
669 if (ul_id > MAX_PERIPH_ID) {
\r
674 if ((PMC->PMC_PCSR0 & (1u << ul_id)) == (1u << ul_id)) {
\r
675 PMC->PMC_PCDR0 = 1 << ul_id;
\r
677 #if (SAM3S || SAM3XA || SAM4S || SAM4E)
\r
680 if ((PMC->PMC_PCSR1 & (1u << ul_id)) == (1u << ul_id)) {
\r
681 PMC->PMC_PCDR1 = 1 << ul_id;
\r
689 * \brief Enable all peripheral clocks.
\r
691 void pmc_enable_all_periph_clk(void)
\r
693 PMC->PMC_PCER0 = PMC_MASK_STATUS0;
\r
694 while ((PMC->PMC_PCSR0 & PMC_MASK_STATUS0) != PMC_MASK_STATUS0);
\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
703 * \brief Disable all peripheral clocks.
\r
705 void pmc_disable_all_periph_clk(void)
\r
707 PMC->PMC_PCDR0 = PMC_MASK_STATUS0;
\r
708 while ((PMC->PMC_PCSR0 & PMC_MASK_STATUS0) != 0);
\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
717 * \brief Check if the specified peripheral clock is enabled.
\r
719 * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
\r
721 * \param ul_id Peripheral ID (ID_xxx).
\r
723 * \retval 0 Peripheral clock is disabled or unknown.
\r
724 * \retval 1 Peripheral clock is enabled.
\r
726 uint32_t pmc_is_periph_clk_enabled(uint32_t ul_id)
\r
728 if (ul_id > MAX_PERIPH_ID) {
\r
732 #if (SAM3S || SAM3XA || SAM4S || SAM4E)
\r
735 if ((PMC->PMC_PCSR0 & (1u << ul_id))) {
\r
740 #if (SAM3S || SAM3XA || SAM4S || SAM4E)
\r
743 if ((PMC->PMC_PCSR1 & (1u << ul_id))) {
\r
753 * \brief Set the prescaler for the specified programmable clock.
\r
755 * \param ul_id Peripheral ID.
\r
756 * \param ul_pres Prescaler value.
\r
758 void pmc_pck_set_prescaler(uint32_t ul_id, uint32_t ul_pres)
\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
767 * \brief Set the source oscillator for the specified programmable clock.
\r
769 * \param ul_id Peripheral ID.
\r
770 * \param ul_source Source selection value.
\r
772 void pmc_pck_set_source(uint32_t ul_id, uint32_t ul_source)
\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
781 * \brief Switch programmable clock source selection to slow clock.
\r
783 * \param ul_id Id of the programmable clock.
\r
784 * \param ul_pres Programmable clock prescaler.
\r
786 * \retval 0 Success.
\r
787 * \retval 1 Timeout error.
\r
789 uint32_t pmc_switch_pck_to_sclk(uint32_t ul_id, uint32_t ul_pres)
\r
791 uint32_t ul_timeout;
\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
805 * \brief Switch programmable clock source selection to main clock.
\r
807 * \param ul_id Id of the programmable clock.
\r
808 * \param ul_pres Programmable clock prescaler.
\r
810 * \retval 0 Success.
\r
811 * \retval 1 Timeout error.
\r
813 uint32_t pmc_switch_pck_to_mainck(uint32_t ul_id, uint32_t ul_pres)
\r
815 uint32_t ul_timeout;
\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
829 * \brief Switch programmable clock source selection to PLLA clock.
\r
831 * \param ul_id Id of the programmable clock.
\r
832 * \param ul_pres Programmable clock prescaler.
\r
834 * \retval 0 Success.
\r
835 * \retval 1 Timeout error.
\r
837 uint32_t pmc_switch_pck_to_pllack(uint32_t ul_id, uint32_t ul_pres)
\r
839 uint32_t ul_timeout;
\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
852 #if (SAM3S || SAM4S)
\r
854 * \brief Switch programmable clock source selection to PLLB clock.
\r
856 * \param ul_id Id of the programmable clock.
\r
857 * \param ul_pres Programmable clock prescaler.
\r
859 * \retval 0 Success.
\r
860 * \retval 1 Timeout error.
\r
862 uint32_t pmc_switch_pck_to_pllbck(uint32_t ul_id, uint32_t ul_pres)
\r
864 uint32_t ul_timeout;
\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
870 if (ul_timeout == 0) {
\r
879 #if (SAM3XA || SAM3U)
\r
881 * \brief Switch programmable clock source selection to UPLL clock.
\r
883 * \param ul_id Id of the programmable clock.
\r
884 * \param ul_pres Programmable clock prescaler.
\r
886 * \retval 0 Success.
\r
887 * \retval 1 Timeout error.
\r
889 uint32_t pmc_switch_pck_to_upllck(uint32_t ul_id, uint32_t ul_pres)
\r
891 uint32_t ul_timeout;
\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
897 if (ul_timeout == 0) {
\r
907 * \brief Enable the specified programmable clock.
\r
909 * \param ul_id Id of the programmable clock.
\r
911 void pmc_enable_pck(uint32_t ul_id)
\r
913 PMC->PMC_SCER = PMC_SCER_PCK0 << ul_id;
\r
917 * \brief Disable the specified programmable clock.
\r
919 * \param ul_id Id of the programmable clock.
\r
921 void pmc_disable_pck(uint32_t ul_id)
\r
923 PMC->PMC_SCDR = PMC_SCER_PCK0 << ul_id;
\r
927 * \brief Enable all programmable clocks.
\r
929 void pmc_enable_all_pck(void)
\r
931 PMC->PMC_SCER = PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2;
\r
935 * \brief Disable all programmable clocks.
\r
937 void pmc_disable_all_pck(void)
\r
939 PMC->PMC_SCDR = PMC_SCDR_PCK0 | PMC_SCDR_PCK1 | PMC_SCDR_PCK2;
\r
943 * \brief Check if the specified programmable clock is enabled.
\r
945 * \param ul_id Id of the programmable clock.
\r
947 * \retval 0 Programmable clock is disabled or unknown.
\r
948 * \retval 1 Programmable clock is enabled.
\r
950 uint32_t pmc_is_pck_enabled(uint32_t ul_id)
\r
956 return (PMC->PMC_SCSR & (PMC_SCSR_PCK0 << ul_id));
\r
959 #if (SAM3S || SAM3XA || SAM4S || SAM4E)
\r
961 * \brief Switch UDP (USB) clock source selection to PLLA clock.
\r
963 * \param ul_usbdiv Clock divisor.
\r
965 void pmc_switch_udpck_to_pllack(uint32_t ul_usbdiv)
\r
967 PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv);
\r
971 #if (SAM3S || SAM4S)
\r
973 * \brief Switch UDP (USB) clock source selection to PLLB clock.
\r
975 * \param ul_usbdiv Clock divisor.
\r
977 void pmc_switch_udpck_to_pllbck(uint32_t ul_usbdiv)
\r
979 PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv) | PMC_USB_USBS;
\r
985 * \brief Switch UDP (USB) clock source selection to UPLL clock.
\r
987 * \param dw_usbdiv Clock divisor.
\r
989 void pmc_switch_udpck_to_upllck(uint32_t ul_usbdiv)
\r
991 PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(ul_usbdiv);
\r
995 #if (SAM3S || SAM3XA || SAM4S || SAM4E)
\r
997 * \brief Enable UDP (USB) clock.
\r
999 void pmc_enable_udpck(void)
\r
1001 # if (SAM3S || SAM4S || SAM4E)
\r
1002 PMC->PMC_SCER = PMC_SCER_UDP;
\r
1004 PMC->PMC_SCER = PMC_SCER_UOTGCLK;
\r
1009 * \brief Disable UDP (USB) clock.
\r
1011 void pmc_disable_udpck(void)
\r
1013 # if (SAM3S || SAM4S || SAM4E)
\r
1014 PMC->PMC_SCDR = PMC_SCDR_UDP;
\r
1016 PMC->PMC_SCDR = PMC_SCDR_UOTGCLK;
\r
1022 * \brief Enable PMC interrupts.
\r
1024 * \param ul_sources Interrupt sources bit map.
\r
1026 void pmc_enable_interrupt(uint32_t ul_sources)
\r
1028 PMC->PMC_IER = ul_sources;
\r
1032 * \brief Disable PMC interrupts.
\r
1034 * \param ul_sources Interrupt sources bit map.
\r
1036 void pmc_disable_interrupt(uint32_t ul_sources)
\r
1038 PMC->PMC_IDR = ul_sources;
\r
1042 * \brief Get PMC interrupt mask.
\r
1044 * \return The interrupt mask value.
\r
1046 uint32_t pmc_get_interrupt_mask(void)
\r
1048 return PMC->PMC_IMR;
\r
1052 * \brief Get current status.
\r
1054 * \return The current PMC status.
\r
1056 uint32_t pmc_get_status(void)
\r
1058 return PMC->PMC_SR;
\r
1062 * \brief Set the wake-up inputs for fast startup mode registers
\r
1063 * (event generation).
\r
1065 * \param ul_inputs Wake up inputs to enable.
\r
1067 void pmc_set_fast_startup_input(uint32_t ul_inputs)
\r
1069 ul_inputs &= PMC_FAST_STARTUP_Msk;
\r
1070 PMC->PMC_FSMR |= ul_inputs;
\r
1074 * \brief Clear the wake-up inputs for fast startup mode registers
\r
1075 * (remove event generation).
\r
1077 * \param ul_inputs Wake up inputs to disable.
\r
1079 void pmc_clr_fast_startup_input(uint32_t ul_inputs)
\r
1081 ul_inputs &= PMC_FAST_STARTUP_Msk;
\r
1082 PMC->PMC_FSMR &= ~ul_inputs;
\r
1086 * \brief Enable Sleep Mode.
\r
1087 * Enter condition: (WFE or WFI) + (SLEEPDEEP bit = 0) + (LPM bit = 0)
\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
1093 void pmc_enable_sleepmode(uint8_t uc_type)
\r
1095 #if !defined(SAM4S) || !defined(SAM4E) || !defined(SAM4N)
\r
1096 PMC->PMC_FSMR &= (uint32_t) ~ PMC_FSMR_LPM; // Enter Sleep mode
\r
1098 SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk; // Deep sleep
\r
1100 #if (SAM4S || SAM4E || SAM4N)
\r
1104 if (uc_type == 0) {
\r
1112 #if (SAM4S || SAM4E || SAM4N)
\r
1113 static uint32_t ul_flash_in_wait_mode = PMC_WAIT_MODE_FLASH_DEEP_POWERDOWN;
\r
1115 * \brief Set the embedded flash state in wait mode
\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
1120 void pmc_set_flash_in_wait_mode(uint32_t ul_flash_state)
\r
1122 ul_flash_in_wait_mode = ul_flash_state;
\r
1126 * \brief Enable Wait Mode. Enter condition: (WAITMODE bit = 1) +
\r
1127 * (SLEEPDEEP bit = 0) + FLPM
\r
1129 void pmc_enable_waitmode(void)
\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
1139 /* Clear SLEEPDEEP bit */
\r
1140 SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk;
\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
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
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
1159 /* Set the WAITMODE bit = 1 */
\r
1160 PMC->CKGR_MOR |= CKGR_MOR_KEY(0x37u) | CKGR_MOR_WAITMODE;
\r
1162 /* Waiting for Master Clock Ready MCKRDY = 1 */
\r
1163 while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
\r
1165 /* Waiting for MOSCRCEN bit cleared is strongly recommended
\r
1166 * to ensure that the core will not execute undesired instructions
\r
1168 for (i = 0; i < 500; i++) {
\r
1171 while (!(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN));
\r
1173 /* Restore EFC FMR setting */
\r
1174 #if defined(ID_EFC)
\r
1175 EFC->EEFC_FMR = fmr_backup;
\r
1177 #if defined(ID_EFC0)
\r
1178 EFC0->EEFC_FMR = fmr0_backup;
\r
1180 #if defined(ID_EFC1)
\r
1181 EFC1->EEFC_FMR = fmr1_backup;
\r
1186 * \brief Enable Wait Mode. Enter condition: WFE + (SLEEPDEEP bit = 0) +
\r
1189 void pmc_enable_waitmode(void)
\r
1193 PMC->PMC_FSMR |= PMC_FSMR_LPM; /* Enter Wait mode */
\r
1194 SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk; /* Deep sleep */
\r
1197 /* Waiting for MOSCRCEN bit cleared is strongly recommended
\r
1198 * to ensure that the core will not execute undesired instructions
\r
1200 for (i = 0; i < 500; i++) {
\r
1203 while (!(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN));
\r
1208 * \brief Enable Backup Mode. Enter condition: WFE/(VROFF bit = 1) +
\r
1209 * (SLEEPDEEP bit = 1)
\r
1211 void pmc_enable_backupmode(void)
\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
1222 * \brief Enable Clock Failure Detector.
\r
1224 void pmc_enable_clock_failure_detector(void)
\r
1226 uint32_t ul_reg = PMC->CKGR_MOR;
\r
1228 PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_CFDEN | ul_reg;
\r
1232 * \brief Disable Clock Failure Detector.
\r
1234 void pmc_disable_clock_failure_detector(void)
\r
1236 uint32_t ul_reg = PMC->CKGR_MOR & (~CKGR_MOR_CFDEN);
\r
1238 PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | ul_reg;
\r
1243 * \brief Enable Slow Crystal Oscillator Frequency Monitoring.
\r
1245 void pmc_enable_sclk_osc_freq_monitor(void)
\r
1247 uint32_t ul_reg = PMC->CKGR_MOR;
\r
1249 PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_XT32KFME | ul_reg;
\r
1253 * \brief Disable Slow Crystal Oscillator Frequency Monitoring.
\r
1255 void pmc_disable_sclk_osc_freq_monitor(void)
\r
1257 uint32_t ul_reg = PMC->CKGR_MOR & (~CKGR_MOR_XT32KFME);
\r
1259 PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | ul_reg;
\r
1264 * \brief Enable or disable write protect of PMC registers.
\r
1266 * \param ul_enable 1 to enable, 0 to disable.
\r
1268 void pmc_set_writeprotect(uint32_t ul_enable)
\r
1271 PMC->PMC_WPMR = PMC_WPMR_WPKEY_VALUE | PMC_WPMR_WPEN;
\r
1273 PMC->PMC_WPMR = PMC_WPMR_WPKEY_VALUE;
\r
1278 * \brief Return write protect status.
\r
1280 * \retval 0 Protection disabled.
\r
1281 * \retval 1 Protection enabled.
\r
1283 uint32_t pmc_get_writeprotect_status(void)
\r
1285 return PMC->PMC_WPMR & PMC_WPMR_WPEN;
\r
1290 #ifdef __cplusplus
\r