4 * \brief Power Management Controller (PMC) driver for SAM.
\r
6 * Copyright (c) 2011-2012 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
65 * \defgroup sam_drivers_pmc_group Power Management Controller (PMC)
\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
77 * \brief Set the prescaler of the MCK.
\r
79 * \param ul_pres Prescaler value.
\r
81 void pmc_mck_set_prescaler(uint32_t ul_pres)
\r
84 (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;
\r
85 while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
\r
89 * \brief Set the source of the MCK.
\r
91 * \param ul_source Source selection value.
\r
93 void pmc_mck_set_source(uint32_t ul_source)
\r
96 (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | ul_source;
\r
97 while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
\r
101 * \brief Switch master clock source selection to slow clock.
\r
103 * \param ul_pres Processor clock prescaler.
\r
105 * \retval 0 Success.
\r
106 * \retval 1 Timeout error.
\r
108 uint32_t pmc_switch_mck_to_sclk(uint32_t ul_pres)
\r
110 uint32_t ul_timeout;
\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
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
130 * \brief Switch master clock source selection to main clock.
\r
132 * \param ul_pres Processor clock prescaler.
\r
134 * \retval 0 Success.
\r
135 * \retval 1 Timeout error.
\r
137 uint32_t pmc_switch_mck_to_mainck(uint32_t ul_pres)
\r
139 uint32_t ul_timeout;
\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
145 if (ul_timeout == 0) {
\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
153 if (ul_timeout == 0) {
\r
162 * \brief Switch master clock source selection to PLLA clock.
\r
164 * \param ul_pres Processor clock prescaler.
\r
166 * \retval 0 Success.
\r
167 * \retval 1 Timeout error.
\r
169 uint32_t pmc_switch_mck_to_pllack(uint32_t ul_pres)
\r
171 uint32_t ul_timeout;
\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
176 if (ul_timeout == 0) {
\r
181 PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |
\r
182 PMC_MCKR_CSS_PLLA_CLK;
\r
184 for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
\r
186 if (ul_timeout == 0) {
\r
194 #if (SAM3S || SAM4S)
\r
196 * \brief Switch master clock source selection to PLLB clock.
\r
198 * \param ul_pres Processor clock prescaler.
\r
200 * \retval 0 Success.
\r
201 * \retval 1 Timeout error.
\r
203 uint32_t pmc_switch_mck_to_pllbck(uint32_t ul_pres)
\r
205 uint32_t ul_timeout;
\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
210 if (ul_timeout == 0) {
\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
219 if (ul_timeout == 0) {
\r
228 #if (SAM3XA || SAM3U)
\r
230 * \brief Switch master clock source selection to UPLL clock.
\r
232 * \param ul_pres Processor clock prescaler.
\r
234 * \retval 0 Success.
\r
235 * \retval 1 Timeout error.
\r
237 uint32_t pmc_switch_mck_to_upllck(uint32_t ul_pres)
\r
239 uint32_t ul_timeout;
\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
244 if (ul_timeout == 0) {
\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
253 if (ul_timeout == 0) {
\r
263 * \brief Switch slow clock source selection to external 32k (Xtal or Bypass).
\r
265 * \note This function disables the PLLs.
\r
267 * \note Switching SCLK back to 32krc is only possible by shutting down the VDDIO
\r
270 * \param ul_bypass 0 for Xtal, 1 for bypass.
\r
272 void pmc_switch_sclk_to_32kxtal(uint32_t ul_bypass)
\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
280 SUPC->SUPC_CR |= SUPC_CR_KEY(SUPC_KEY_VALUE) | SUPC_CR_XTALSEL;
\r
284 * \brief Check if the external 32k Xtal is ready.
\r
286 * \retval 1 External 32k Xtal is ready.
\r
287 * \retval 0 External 32k Xtal is not ready.
\r
289 uint32_t pmc_osc_is_ready_32kxtal(void)
\r
291 return ((SUPC->SUPC_SR & SUPC_SR_OSCSEL)
\r
292 && (PMC->PMC_SR & PMC_SR_OSCSELS));
\r
296 * \brief Switch main clock source selection to internal fast RC.
\r
298 * \param ul_moscrcf Fast RC oscillator(4/8/12Mhz).
\r
300 * \retval 0 Success.
\r
301 * \retval 1 Timeout error.
\r
302 * \retval 2 Invalid frequency.
\r
304 void pmc_switch_mainck_to_fastrc(uint32_t ul_moscrcf)
\r
306 uint32_t ul_needXTEN = 0;
\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
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
321 /* Wait the Fast RC to stabilize */
\r
322 while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));
\r
324 /* Switch to Fast RC */
\r
325 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) | PMC_CKGR_MOR_KEY_VALUE;
\r
327 /* Disable xtal oscillator */
\r
329 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |
\r
330 PMC_CKGR_MOR_KEY_VALUE;
\r
335 * \brief Enable fast RC oscillator.
\r
337 * \param ul_rc Fast RC oscillator(4/8/12Mhz).
\r
339 void pmc_osc_enable_fastrc(uint32_t ul_rc)
\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
349 * \brief Disable the internal fast RC.
\r
351 void pmc_osc_disable_fastrc(void)
\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
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
363 * \note If used in Xtal mode, the Xtal is automatically enabled.
\r
365 * \param ul_bypass 0 for Xtal, 1 for bypass.
\r
367 * \retval 0 Success.
\r
368 * \retval 1 Timeout error.
\r
370 void pmc_switch_mainck_to_xtal(uint32_t ul_bypass)
\r
372 /* Enable Main Xtal oscillator */
\r
374 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |
\r
375 PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCXTBY |
\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
384 PMC->CKGR_MOR |= PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_MOSCSEL;
\r
389 * \brief Disable the external Xtal.
\r
391 * \param ul_bypass 0 for Xtal, 1 for bypass.
\r
393 void pmc_osc_disable_xtal(uint32_t ul_bypass)
\r
395 /* Disable xtal oscillator */
\r
397 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) |
\r
398 PMC_CKGR_MOR_KEY_VALUE;
\r
400 PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |
\r
401 PMC_CKGR_MOR_KEY_VALUE;
\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
409 * \retval 1 Xtal is ready.
\r
410 * \retval 0 Xtal is not ready.
\r
412 uint32_t pmc_osc_is_ready_mainck(void)
\r
414 return PMC->PMC_SR & PMC_SR_MOSCSELS;
\r
418 * \brief Enable PLLA clock.
\r
420 * \param mula PLLA multiplier.
\r
421 * \param pllacount PLLA counter.
\r
422 * \param diva Divider.
\r
424 void pmc_enable_pllack(uint32_t mula, uint32_t pllacount, uint32_t diva)
\r
426 /* first disable the PLL to unlock the lock!*/
\r
427 pmc_disable_pllack();
\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
435 * \brief Disable PLLA clock.
\r
437 void pmc_disable_pllack(void)
\r
439 PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0);
\r
443 * \brief Is PLLA locked?
\r
445 * \retval 0 Not locked.
\r
446 * \retval 1 Locked.
\r
448 uint32_t pmc_is_locked_pllack(void)
\r
450 return (PMC->PMC_SR & PMC_SR_LOCKA);
\r
453 #if (SAM3S || SAM4S)
\r
455 * \brief Enable PLLB clock.
\r
457 * \param mulb PLLB multiplier.
\r
458 * \param pllbcount PLLB counter.
\r
459 * \param divb Divider.
\r
461 void pmc_enable_pllbck(uint32_t mulb, uint32_t pllbcount, uint32_t divb)
\r
463 /* first disable the PLL to unlock the lock!*/
\r
464 pmc_disable_pllbck();
\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
473 * \brief Disable PLLB clock.
\r
475 void pmc_disable_pllbck(void)
\r
477 PMC->CKGR_PLLBR = CKGR_PLLBR_MULB(0);
\r
481 * \brief Is PLLB locked?
\r
483 * \retval 0 Not locked.
\r
484 * \retval 1 Locked.
\r
486 uint32_t pmc_is_locked_pllbck(void)
\r
488 return (PMC->PMC_SR & PMC_SR_LOCKB);
\r
492 #if (SAM3XA || SAM3U)
\r
494 * \brief Enable UPLL clock.
\r
496 void pmc_enable_upll_clock(void)
\r
498 PMC->CKGR_UCKR = CKGR_UCKR_UPLLCOUNT(3) | CKGR_UCKR_UPLLEN;
\r
500 /* Wait UTMI PLL Lock Status */
\r
501 while (!(PMC->PMC_SR & PMC_SR_LOCKU));
\r
505 * \brief Disable UPLL clock.
\r
507 void pmc_disable_upll_clock(void)
\r
509 PMC->CKGR_UCKR &= ~CKGR_UCKR_UPLLEN;
\r
513 * \brief Is UPLL locked?
\r
515 * \retval 0 Not locked.
\r
516 * \retval 1 Locked.
\r
518 uint32_t pmc_is_locked_upll(void)
\r
520 return (PMC->PMC_SR & PMC_SR_LOCKU);
\r
525 * \brief Enable the specified peripheral clock.
\r
527 * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
\r
529 * \param ul_id Peripheral ID (ID_xxx).
\r
531 * \retval 0 Success.
\r
532 * \retval 1 Invalid parameter.
\r
534 uint32_t pmc_enable_periph_clk(uint32_t ul_id)
\r
536 if (ul_id > MAX_PERIPH_ID) {
\r
541 if ((PMC->PMC_PCSR0 & (1u << ul_id)) != (1u << ul_id)) {
\r
542 PMC->PMC_PCER0 = 1 << ul_id;
\r
544 #if (SAM3S || SAM3XA || SAM4S)
\r
547 if ((PMC->PMC_PCSR1 & (1u << ul_id)) != (1u << ul_id)) {
\r
548 PMC->PMC_PCER1 = 1 << ul_id;
\r
557 * \brief Disable the specified peripheral clock.
\r
559 * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
\r
561 * \param ul_id Peripheral ID (ID_xxx).
\r
563 * \retval 0 Success.
\r
564 * \retval 1 Invalid parameter.
\r
566 uint32_t pmc_disable_periph_clk(uint32_t ul_id)
\r
568 if (ul_id > MAX_PERIPH_ID) {
\r
573 if ((PMC->PMC_PCSR0 & (1u << ul_id)) == (1u << ul_id)) {
\r
574 PMC->PMC_PCDR0 = 1 << ul_id;
\r
576 #if (SAM3S || SAM3XA || SAM4S)
\r
579 if ((PMC->PMC_PCSR1 & (1u << ul_id)) == (1u << ul_id)) {
\r
580 PMC->PMC_PCDR1 = 1 << ul_id;
\r
588 * \brief Enable all peripheral clocks.
\r
590 void pmc_enable_all_periph_clk(void)
\r
592 PMC->PMC_PCER0 = PMC_MASK_STATUS0;
\r
593 while ((PMC->PMC_PCSR0 & PMC_MASK_STATUS0) != PMC_MASK_STATUS0);
\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
602 * \brief Disable all peripheral clocks.
\r
604 void pmc_disable_all_periph_clk(void)
\r
606 PMC->PMC_PCDR0 = PMC_MASK_STATUS0;
\r
607 while ((PMC->PMC_PCSR0 & PMC_MASK_STATUS0) != 0);
\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
616 * \brief Check if the specified peripheral clock is enabled.
\r
618 * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
\r
620 * \param ul_id Peripheral ID (ID_xxx).
\r
622 * \retval 0 Peripheral clock is disabled or unknown.
\r
623 * \retval 1 Peripheral clock is enabled.
\r
625 uint32_t pmc_is_periph_clk_enabled(uint32_t ul_id)
\r
627 if (ul_id > MAX_PERIPH_ID) {
\r
631 #if (SAM3S || SAM3XA || SAM4S)
\r
634 if ((PMC->PMC_PCSR0 & (1u << ul_id))) {
\r
639 #if (SAM3S || SAM3XA || SAM4S)
\r
642 if ((PMC->PMC_PCSR1 & (1u << ul_id))) {
\r
652 * \brief Set the prescaler for the specified programmable clock.
\r
654 * \param ul_id Peripheral ID.
\r
655 * \param ul_pres Prescaler value.
\r
657 void pmc_pck_set_prescaler(uint32_t ul_id, uint32_t ul_pres)
\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
666 * \brief Set the source oscillator for the specified programmable clock.
\r
668 * \param ul_id Peripheral ID.
\r
669 * \param ul_source Source selection value.
\r
671 void pmc_pck_set_source(uint32_t ul_id, uint32_t ul_source)
\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
680 * \brief Switch programmable clock source selection to slow clock.
\r
682 * \param ul_id Id of the programmable clock.
\r
683 * \param ul_pres Programmable clock prescaler.
\r
685 * \retval 0 Success.
\r
686 * \retval 1 Timeout error.
\r
688 uint32_t pmc_switch_pck_to_sclk(uint32_t ul_id, uint32_t ul_pres)
\r
690 uint32_t ul_timeout;
\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
695 if (ul_timeout == 0) {
\r
704 * \brief Switch programmable clock source selection to main clock.
\r
706 * \param ul_id Id of the programmable clock.
\r
707 * \param ul_pres Programmable clock prescaler.
\r
709 * \retval 0 Success.
\r
710 * \retval 1 Timeout error.
\r
712 uint32_t pmc_switch_pck_to_mainck(uint32_t ul_id, uint32_t ul_pres)
\r
714 uint32_t ul_timeout;
\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
719 if (ul_timeout == 0) {
\r
728 * \brief Switch programmable clock source selection to PLLA clock.
\r
730 * \param ul_id Id of the programmable clock.
\r
731 * \param ul_pres Programmable clock prescaler.
\r
733 * \retval 0 Success.
\r
734 * \retval 1 Timeout error.
\r
736 uint32_t pmc_switch_pck_to_pllack(uint32_t ul_id, uint32_t ul_pres)
\r
738 uint32_t ul_timeout;
\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
743 if (ul_timeout == 0) {
\r
751 #if (SAM3S || SAM4S)
\r
753 * \brief Switch programmable clock source selection to PLLB clock.
\r
755 * \param ul_id Id of the programmable clock.
\r
756 * \param ul_pres Programmable clock prescaler.
\r
758 * \retval 0 Success.
\r
759 * \retval 1 Timeout error.
\r
761 uint32_t pmc_switch_pck_to_pllbck(uint32_t ul_id, uint32_t ul_pres)
\r
763 uint32_t ul_timeout;
\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
769 if (ul_timeout == 0) {
\r
778 #if (SAM3XA || SAM3U)
\r
780 * \brief Switch programmable clock source selection to UPLL clock.
\r
782 * \param ul_id Id of the programmable clock.
\r
783 * \param ul_pres Programmable clock prescaler.
\r
785 * \retval 0 Success.
\r
786 * \retval 1 Timeout error.
\r
788 uint32_t pmc_switch_pck_to_upllck(uint32_t ul_id, uint32_t ul_pres)
\r
790 uint32_t ul_timeout;
\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
796 if (ul_timeout == 0) {
\r
806 * \brief Enable the specified programmable clock.
\r
808 * \param ul_id Id of the programmable clock.
\r
810 void pmc_enable_pck(uint32_t ul_id)
\r
812 PMC->PMC_SCER = PMC_SCER_PCK0 << ul_id;
\r
816 * \brief Disable the specified programmable clock.
\r
818 * \param ul_id Id of the programmable clock.
\r
820 void pmc_disable_pck(uint32_t ul_id)
\r
822 PMC->PMC_SCDR = PMC_SCER_PCK0 << ul_id;
\r
826 * \brief Enable all programmable clocks.
\r
828 void pmc_enable_all_pck(void)
\r
830 PMC->PMC_SCER = PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2;
\r
834 * \brief Disable all programmable clocks.
\r
836 void pmc_disable_all_pck(void)
\r
838 PMC->PMC_SCDR = PMC_SCDR_PCK0 | PMC_SCDR_PCK1 | PMC_SCDR_PCK2;
\r
842 * \brief Check if the specified programmable clock is enabled.
\r
844 * \param ul_id Id of the programmable clock.
\r
846 * \retval 0 Programmable clock is disabled or unknown.
\r
847 * \retval 1 Programmable clock is enabled.
\r
849 uint32_t pmc_is_pck_enabled(uint32_t ul_id)
\r
855 return (PMC->PMC_SCSR & (PMC_SCSR_PCK0 << ul_id));
\r
858 #if (SAM3S || SAM3XA || SAM4S)
\r
860 * \brief Switch UDP (USB) clock source selection to PLLA clock.
\r
862 * \param ul_usbdiv Clock divisor.
\r
864 void pmc_switch_udpck_to_pllack(uint32_t ul_usbdiv)
\r
866 PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv);
\r
870 #if (SAM3S || SAM4S)
\r
872 * \brief Switch UDP (USB) clock source selection to PLLB clock.
\r
874 * \param ul_usbdiv Clock divisor.
\r
876 void pmc_switch_udpck_to_pllbck(uint32_t ul_usbdiv)
\r
878 PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv) | PMC_USB_USBS;
\r
884 * \brief Switch UDP (USB) clock source selection to UPLL clock.
\r
886 * \param dw_usbdiv Clock divisor.
\r
888 void pmc_switch_udpck_to_upllck(uint32_t ul_usbdiv)
\r
890 PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(ul_usbdiv);
\r
894 #if (SAM3S || SAM3XA || SAM4S)
\r
896 * \brief Enable UDP (USB) clock.
\r
898 void pmc_enable_udpck(void)
\r
900 # if (SAM3S || SAM4S)
\r
901 PMC->PMC_SCER = PMC_SCER_UDP;
\r
903 PMC->PMC_SCER = PMC_SCER_UOTGCLK;
\r
908 * \brief Disable UDP (USB) clock.
\r
910 void pmc_disable_udpck(void)
\r
912 # if (SAM3S || SAM4S)
\r
913 PMC->PMC_SCDR = PMC_SCDR_UDP;
\r
915 PMC->PMC_SCDR = PMC_SCDR_UOTGCLK;
\r
921 * \brief Enable PMC interrupts.
\r
923 * \param ul_sources Interrupt sources bit map.
\r
925 void pmc_enable_interrupt(uint32_t ul_sources)
\r
927 PMC->PMC_IER = ul_sources;
\r
931 * \brief Disable PMC interrupts.
\r
933 * \param ul_sources Interrupt sources bit map.
\r
935 void pmc_disable_interrupt(uint32_t ul_sources)
\r
937 PMC->PMC_IDR = ul_sources;
\r
941 * \brief Get PMC interrupt mask.
\r
943 * \return The interrupt mask value.
\r
945 uint32_t pmc_get_interrupt_mask(void)
\r
947 return PMC->PMC_IMR;
\r
951 * \brief Get current status.
\r
953 * \return The current PMC status.
\r
955 uint32_t pmc_get_status(void)
\r
957 return PMC->PMC_SR;
\r
961 * \brief Set the wake-up inputs for fast startup mode registers (event generation).
\r
963 * \param ul_inputs Wake up inputs to enable.
\r
965 void pmc_set_fast_startup_input(uint32_t ul_inputs)
\r
967 ul_inputs &= PMC_FAST_STARTUP_Msk;
\r
968 PMC->PMC_FSMR |= ul_inputs;
\r
972 * \brief Clear the wake-up inputs for fast startup mode registers (remove event generation).
\r
974 * \param ul_inputs Wake up inputs to disable.
\r
976 void pmc_clr_fast_startup_input(uint32_t ul_inputs)
\r
978 ul_inputs &= PMC_FAST_STARTUP_Msk;
\r
979 PMC->PMC_FSMR &= ~ul_inputs;
\r
983 * \brief Enable Sleep Mode.
\r
984 * Enter condition: (WFE or WFI) + (SLEEPDEEP bit = 0) + (LPM bit = 0)
\r
986 * \param uc_type 0 for wait for interrupt, 1 for wait for event.
\r
988 void pmc_enable_sleepmode(uint8_t uc_type)
\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
993 if (uc_type == 0) {
\r
1001 * \brief Enable Wait Mode.
\r
1002 * Enter condition: WFE + (SLEEPDEEP bit = 0) + (LPM bit = 1)
\r
1004 void pmc_enable_waitmode(void)
\r
1008 PMC->PMC_FSMR |= PMC_FSMR_LPM; // Enter Wait mode
\r
1009 SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk; // Deep sleep
\r
1012 /* Waiting for MOSCRCEN bit cleared is strongly recommended
\r
1013 * to ensure that the core will not execute undesired instructions
\r
1015 for (i = 0; i < 500; i++) {
\r
1018 while (!(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN));
\r
1022 * \brief Enable Backup Mode.
\r
1023 * Enter condition: WFE + (SLEEPDEEP bit = 1)
\r
1025 void pmc_enable_backupmode(void)
\r
1027 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
\r
1032 * \brief Enable Clock Failure Detector.
\r
1034 void pmc_enable_clock_failure_detector(void)
\r
1036 uint32_t ul_reg = PMC->CKGR_MOR;
\r
1038 PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | CKGR_MOR_CFDEN | ul_reg;
\r
1042 * \brief Disable Clock Failure Detector.
\r
1044 void pmc_disable_clock_failure_detector(void)
\r
1046 uint32_t ul_reg = PMC->CKGR_MOR & (~CKGR_MOR_CFDEN);
\r
1048 PMC->CKGR_MOR = PMC_CKGR_MOR_KEY_VALUE | ul_reg;
\r
1052 * \brief Enable or disable write protect of PMC registers.
\r
1054 * \param ul_enable 1 to enable, 0 to disable.
\r
1056 void pmc_set_writeprotect(uint32_t ul_enable)
\r
1059 PMC->PMC_WPMR = PMC_WPMR_WPKEY_VALUE | PMC_WPMR_WPEN;
\r
1061 PMC->PMC_WPMR = PMC_WPMR_WPKEY_VALUE;
\r
1066 * \brief Return write protect status.
\r
1068 * \retval 0 Protection disabled.
\r
1069 * \retval 1 Protection enabled.
\r
1071 uint32_t pmc_get_writeprotect_status(void)
\r
1073 return PMC->PMC_WPMR & PMC_WPMR_WPEN;
\r
1078 #ifdef __cplusplus
\r