xref: /btstack/port/samv71-xplained-atwilc3000/ASF/sam/drivers/pmc/pmc.c (revision 1b2596b5303dd8caeea8565532c93cca8dab8cc4)
1 /**
2  * \file
3  *
4  * \brief Power Management Controller (PMC) driver for SAM.
5  *
6  * Copyright (c) 2011-2015 Atmel Corporation. All rights reserved.
7  *
8  * \asf_license_start
9  *
10  * \page License
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright notice,
16  *    this list of conditions and the following disclaimer.
17  *
18  * 2. Redistributions in binary form must reproduce the above copyright notice,
19  *    this list of conditions and the following disclaimer in the documentation
20  *    and/or other materials provided with the distribution.
21  *
22  * 3. The name of Atmel may not be used to endorse or promote products derived
23  *    from this software without specific prior written permission.
24  *
25  * 4. This software may only be redistributed and used in connection with an
26  *    Atmel microcontroller product.
27  *
28  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  *
40  * \asf_license_stop
41  *
42  */
43 /*
44  * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45  */
46 
47 #include "pmc.h"
48 
49 #if (SAM3N)
50 # define MAX_PERIPH_ID    31
51 #elif (SAM3XA)
52 # define MAX_PERIPH_ID    44
53 #elif (SAM3U)
54 # define MAX_PERIPH_ID    29
55 #elif (SAM3S || SAM4S)
56 # define MAX_PERIPH_ID    34
57 #elif (SAM4E)
58 # define MAX_PERIPH_ID    47
59 #elif (SAMV71)
60 # define MAX_PERIPH_ID    63
61 #elif (SAMV70)
62 # define MAX_PERIPH_ID    63
63 #elif (SAME70)
64 # define MAX_PERIPH_ID    63
65 #elif (SAMS70)
66 # define MAX_PERIPH_ID    63
67 #elif (SAM4N)
68 # define MAX_PERIPH_ID    31
69 #elif (SAM4C || SAM4CM || SAM4CP)
70 # define MAX_PERIPH_ID    43
71 #elif (SAMG51)
72 # define MAX_PERIPH_ID    47
73 #elif (SAMG53)
74 # define MAX_PERIPH_ID    47
75 #elif (SAMG54)
76 # define MAX_PERIPH_ID    47
77 #elif (SAMG55)
78 # define MAX_PERIPH_ID    50
79 #endif
80 
81 /// @cond 0
82 /**INDENT-OFF**/
83 #ifdef __cplusplus
84 extern "C" {
85 #endif
86 /**INDENT-ON**/
87 /// @endcond
88 
89 /**
90  * \defgroup sam_drivers_pmc_group Power Management Controller (PMC)
91  *
92  * \par Purpose
93  *
94  * The Power Management Controller (PMC) optimizes power consumption by
95  * controlling all system and user peripheral clocks. The PMC enables/disables
96  * the clock inputs to many of the peripherals and the Cortex-M Processor.
97  *
98  * @{
99  */
100 
101 /**
102  * \brief Set the prescaler of the MCK.
103  *
104  * \param ul_pres Prescaler value.
105  */
pmc_mck_set_prescaler(uint32_t ul_pres)106 void pmc_mck_set_prescaler(uint32_t ul_pres)
107 {
108 	PMC->PMC_MCKR =
109 			(PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;
110 	while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
111 }
112 
113 #if SAMV71 || SAMV70 || SAME70 || SAMS70
114 /**
115  * \brief Set the division of the MCK.
116  *
117  * \param ul_div Division value.
118  */
pmc_mck_set_division(uint32_t ul_div)119 void pmc_mck_set_division(uint32_t ul_div)
120 {
121 	switch (ul_div) {
122 		case 1:
123 			ul_div = PMC_MCKR_MDIV_EQ_PCK;
124 			break;
125 		case 2:
126 			ul_div = PMC_MCKR_MDIV_PCK_DIV2;
127 			break;
128 		case 3:
129 			ul_div = PMC_MCKR_MDIV_PCK_DIV3;
130 			break;
131 		case 4:
132 			ul_div = PMC_MCKR_MDIV_PCK_DIV4;
133 			break;
134 		default:
135 			ul_div = PMC_MCKR_MDIV_EQ_PCK;
136 			break;
137 	}
138 	PMC->PMC_MCKR =
139 			(PMC->PMC_MCKR & (~PMC_MCKR_MDIV_Msk)) | ul_div;
140 	while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
141 }
142 #endif
143 
144 /**
145  * \brief Set the source of the MCK.
146  *
147  * \param ul_source Source selection value.
148  */
pmc_mck_set_source(uint32_t ul_source)149 void pmc_mck_set_source(uint32_t ul_source)
150 {
151 	PMC->PMC_MCKR =
152 			(PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) | ul_source;
153 	while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
154 }
155 
156 /**
157  * \brief Switch master clock source selection to slow clock.
158  *
159  * \param ul_pres Processor clock prescaler.
160  *
161  * \retval 0 Success.
162  * \retval 1 Timeout error.
163  */
pmc_switch_mck_to_sclk(uint32_t ul_pres)164 uint32_t pmc_switch_mck_to_sclk(uint32_t ul_pres)
165 {
166 	uint32_t ul_timeout;
167 
168 	PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |
169 			PMC_MCKR_CSS_SLOW_CLK;
170 	for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
171 			--ul_timeout) {
172 		if (ul_timeout == 0) {
173 			return 1;
174 		}
175 	}
176 
177 	PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;
178 	for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
179 			--ul_timeout) {
180 		if (ul_timeout == 0) {
181 			return 1;
182 		}
183 	}
184 
185 	return 0;
186 }
187 
188 /**
189  * \brief Switch master clock source selection to main clock.
190  *
191  * \param ul_pres Processor clock prescaler.
192  *
193  * \retval 0 Success.
194  * \retval 1 Timeout error.
195  */
pmc_switch_mck_to_mainck(uint32_t ul_pres)196 uint32_t pmc_switch_mck_to_mainck(uint32_t ul_pres)
197 {
198 	uint32_t ul_timeout;
199 
200 	PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |
201 			PMC_MCKR_CSS_MAIN_CLK;
202 	for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
203 			--ul_timeout) {
204 		if (ul_timeout == 0) {
205 			return 1;
206 		}
207 	}
208 
209 	PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;
210 	for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
211 			--ul_timeout) {
212 		if (ul_timeout == 0) {
213 			return 1;
214 		}
215 	}
216 
217 	return 0;
218 }
219 
220 /**
221  * \brief Switch master clock source selection to PLLA clock.
222  *
223  * \param ul_pres Processor clock prescaler.
224  *
225  * \retval 0 Success.
226  * \retval 1 Timeout error.
227  */
pmc_switch_mck_to_pllack(uint32_t ul_pres)228 uint32_t pmc_switch_mck_to_pllack(uint32_t ul_pres)
229 {
230 	uint32_t ul_timeout;
231 
232 	PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;
233 	for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
234 			--ul_timeout) {
235 		if (ul_timeout == 0) {
236 			return 1;
237 		}
238 	}
239 
240 	PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |
241 			PMC_MCKR_CSS_PLLA_CLK;
242 
243 	for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
244 			--ul_timeout) {
245 		if (ul_timeout == 0) {
246 			return 1;
247 		}
248 	}
249 
250 	return 0;
251 }
252 
253 #if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP || SAMG55)
254 /**
255  * \brief Switch master clock source selection to PLLB clock.
256  *
257  * \param ul_pres Processor clock prescaler.
258  *
259  * \retval 0 Success.
260  * \retval 1 Timeout error.
261  */
pmc_switch_mck_to_pllbck(uint32_t ul_pres)262 uint32_t pmc_switch_mck_to_pllbck(uint32_t ul_pres)
263 {
264 	uint32_t ul_timeout;
265 
266 	PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;
267 	for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
268 			--ul_timeout) {
269 		if (ul_timeout == 0) {
270 			return 1;
271 		}
272 	}
273 
274 	PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |
275 			PMC_MCKR_CSS_PLLB_CLK;
276 	for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
277 			--ul_timeout) {
278 		if (ul_timeout == 0) {
279 			return 1;
280 		}
281 	}
282 
283 	return 0;
284 }
285 #endif
286 
287 #if (SAM3XA || SAM3U || SAMV71 || SAMV70 || SAME70 || SAMS70)
288 /**
289  * \brief Switch master clock source selection to UPLL clock.
290  *
291  * \param ul_pres Processor clock prescaler.
292  *
293  * \retval 0 Success.
294  * \retval 1 Timeout error.
295  */
pmc_switch_mck_to_upllck(uint32_t ul_pres)296 uint32_t pmc_switch_mck_to_upllck(uint32_t ul_pres)
297 {
298 	uint32_t ul_timeout;
299 
300 	PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_PRES_Msk)) | ul_pres;
301 	for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
302 			--ul_timeout) {
303 		if (ul_timeout == 0) {
304 			return 1;
305 		}
306 	}
307 
308 	PMC->PMC_MCKR = (PMC->PMC_MCKR & (~PMC_MCKR_CSS_Msk)) |
309 			PMC_MCKR_CSS_UPLL_CLK;
310 	for (ul_timeout = PMC_TIMEOUT; !(PMC->PMC_SR & PMC_SR_MCKRDY);
311 			--ul_timeout) {
312 		if (ul_timeout == 0) {
313 			return 1;
314 		}
315 	}
316 
317 	return 0;
318 }
319 #endif
320 
321 /**
322  * \brief Switch slow clock source selection to external 32k (Xtal or Bypass).
323  *
324  * \note Switching SCLK back to 32krc is only possible by shutting down the
325  *       VDDIO power supply.
326  *
327  * \param ul_bypass 0 for Xtal, 1 for bypass.
328  */
pmc_switch_sclk_to_32kxtal(uint32_t ul_bypass)329 void pmc_switch_sclk_to_32kxtal(uint32_t ul_bypass)
330 {
331 	/* Set Bypass mode if required */
332 	if (ul_bypass == 1) {
333 		SUPC->SUPC_MR |= SUPC_MR_KEY_PASSWD |
334 			SUPC_MR_OSCBYPASS;
335 	}
336 
337 	SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL;
338 }
339 
340 /**
341  * \brief Check if the external 32k Xtal is ready.
342  *
343  * \retval 1 External 32k Xtal is ready.
344  * \retval 0 External 32k Xtal is not ready.
345  */
pmc_osc_is_ready_32kxtal(void)346 uint32_t pmc_osc_is_ready_32kxtal(void)
347 {
348 	return ((SUPC->SUPC_SR & SUPC_SR_OSCSEL)
349 			&& (PMC->PMC_SR & PMC_SR_OSCSELS));
350 }
351 
352 /**
353  * \brief Switch main clock source selection to internal fast RC.
354  *
355  * \param ul_moscrcf Fast RC oscillator(4/8/12Mhz).
356  *
357  * \retval 0 Success.
358  * \retval 1 Timeout error.
359  * \retval 2 Invalid frequency.
360  */
pmc_switch_mainck_to_fastrc(uint32_t ul_moscrcf)361 void pmc_switch_mainck_to_fastrc(uint32_t ul_moscrcf)
362 {
363 	/* Enable Fast RC oscillator but DO NOT switch to RC now */
364 	PMC->CKGR_MOR |= (CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCRCEN);
365 
366 	/* Wait the Fast RC to stabilize */
367 	while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));
368 
369 	/* Change Fast RC oscillator frequency */
370 	PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCF_Msk) |
371 			CKGR_MOR_KEY_PASSWD | ul_moscrcf;
372 
373 	/* Wait the Fast RC to stabilize */
374 	while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));
375 
376 	/* Switch to Fast RC */
377 	PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) |
378 			CKGR_MOR_KEY_PASSWD;
379 }
380 
381 /**
382  * \brief Enable fast RC oscillator.
383  *
384  * \param ul_rc Fast RC oscillator(4/8/12Mhz).
385  */
pmc_osc_enable_fastrc(uint32_t ul_rc)386 void pmc_osc_enable_fastrc(uint32_t ul_rc)
387 {
388 	/* Enable Fast RC oscillator but DO NOT switch to RC */
389 	PMC->CKGR_MOR |= (CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCRCEN);
390 	/* Wait the Fast RC to stabilize */
391 	while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));
392 
393 	/* Change Fast RC oscillator frequency */
394 	PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCF_Msk) |
395 			CKGR_MOR_KEY_PASSWD | ul_rc;
396 	/* Wait the Fast RC to stabilize */
397 	while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));
398 }
399 
400 /**
401  * \brief Disable the internal fast RC.
402  */
pmc_osc_disable_fastrc(void)403 void pmc_osc_disable_fastrc(void)
404 {
405 	/* Disable Fast RC oscillator */
406 	PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCEN &
407 					~CKGR_MOR_MOSCRCF_Msk)
408 				| CKGR_MOR_KEY_PASSWD;
409 }
410 
411 /**
412  * \brief Check if the main fastrc is ready.
413  *
414  * \retval 0 Xtal is not ready, otherwise ready.
415  */
pmc_osc_is_ready_fastrc(void)416 uint32_t pmc_osc_is_ready_fastrc(void)
417 {
418 	return (PMC->PMC_SR & PMC_SR_MOSCRCS);
419 }
420 
421 /**
422  * \brief Enable main XTAL oscillator.
423  *
424  * \param ul_xtal_startup_time Xtal start-up time, in number of slow clocks.
425  */
pmc_osc_enable_main_xtal(uint32_t ul_xtal_startup_time)426 void pmc_osc_enable_main_xtal(uint32_t ul_xtal_startup_time)
427 {
428 	uint32_t mor = PMC->CKGR_MOR;
429 	mor &= ~(CKGR_MOR_MOSCXTBY|CKGR_MOR_MOSCXTEN);
430 	mor |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTEN |
431 			CKGR_MOR_MOSCXTST(ul_xtal_startup_time);
432 	PMC->CKGR_MOR = mor;
433 	/* Wait the main Xtal to stabilize */
434 	while (!(PMC->PMC_SR & PMC_SR_MOSCXTS));
435 }
436 
437 /**
438  * \brief Bypass main XTAL.
439  */
pmc_osc_bypass_main_xtal(void)440 void pmc_osc_bypass_main_xtal(void)
441 {
442 	uint32_t mor = PMC->CKGR_MOR;
443 	mor &= ~(CKGR_MOR_MOSCXTBY|CKGR_MOR_MOSCXTEN);
444 	mor |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTBY;
445 	/* Enable Crystal oscillator but DO NOT switch now. Keep MOSCSEL to 0 */
446 	PMC->CKGR_MOR = mor;
447 	/* The MOSCXTS in PMC_SR is automatically set */
448 }
449 
450 /**
451  * \brief Disable the main Xtal.
452  */
pmc_osc_disable_main_xtal(void)453 void pmc_osc_disable_main_xtal(void)
454 {
455 	uint32_t mor = PMC->CKGR_MOR;
456 	mor &= ~(CKGR_MOR_MOSCXTBY|CKGR_MOR_MOSCXTEN);
457 	PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | mor;
458 }
459 
460 /**
461  * \brief Check if the main crystal is bypassed.
462  *
463  * \retval 0 Xtal is bypassed, otherwise not.
464  */
pmc_osc_is_bypassed_main_xtal(void)465 uint32_t pmc_osc_is_bypassed_main_xtal(void)
466 {
467 	return (PMC->CKGR_MOR & CKGR_MOR_MOSCXTBY);
468 }
469 
470 /**
471  * \brief Check if the main crystal is ready.
472  *
473  * \note If main crystal is bypassed, it's always ready.
474  *
475  * \retval 0 main crystal is not ready, otherwise ready.
476  */
pmc_osc_is_ready_main_xtal(void)477 uint32_t pmc_osc_is_ready_main_xtal(void)
478 {
479 	return (PMC->PMC_SR & PMC_SR_MOSCXTS);
480 }
481 
482 /**
483  * \brief Switch main clock source selection to external Xtal/Bypass.
484  *
485  * \note The function may switch MCK to SCLK if MCK source is MAINCK to avoid
486  *       any system crash.
487  *
488  * \note If used in Xtal mode, the Xtal is automatically enabled.
489  *
490  * \param ul_bypass 0 for Xtal, 1 for bypass.
491  *
492  * \retval 0 Success.
493  * \retval 1 Timeout error.
494  */
pmc_switch_mainck_to_xtal(uint32_t ul_bypass,uint32_t ul_xtal_startup_time)495 void pmc_switch_mainck_to_xtal(uint32_t ul_bypass,
496 		uint32_t ul_xtal_startup_time)
497 {
498 	/* Enable Main Xtal oscillator */
499 	if (ul_bypass) {
500 		PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |
501 				CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTBY |
502 				CKGR_MOR_MOSCSEL;
503 	} else {
504 		PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) |
505 				CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTEN |
506 				CKGR_MOR_MOSCXTST(ul_xtal_startup_time);
507 		/* Wait the Xtal to stabilize */
508 		while (!(PMC->PMC_SR & PMC_SR_MOSCXTS));
509 
510 		PMC->CKGR_MOR |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCSEL;
511 	}
512 }
513 
514 /**
515  * \brief Disable the external Xtal.
516  *
517  * \param ul_bypass 0 for Xtal, 1 for bypass.
518  */
pmc_osc_disable_xtal(uint32_t ul_bypass)519 void pmc_osc_disable_xtal(uint32_t ul_bypass)
520 {
521 	/* Disable xtal oscillator */
522 	if (ul_bypass) {
523 		PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) |
524 				CKGR_MOR_KEY_PASSWD;
525 	} else {
526 		PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |
527 				CKGR_MOR_KEY_PASSWD;
528 	}
529 }
530 
531 /**
532  * \brief Check if the MAINCK is ready. Depending on MOSCEL, MAINCK can be one
533  * of Xtal, bypass or internal RC.
534  *
535  * \retval 1 Xtal is ready.
536  * \retval 0 Xtal is not ready.
537  */
pmc_osc_is_ready_mainck(void)538 uint32_t pmc_osc_is_ready_mainck(void)
539 {
540 	return PMC->PMC_SR & PMC_SR_MOSCSELS;
541 }
542 
543 /**
544  * \brief Select Main Crystal or internal RC as main clock source.
545  *
546  * \note This function will not enable/disable RC or Main Crystal.
547  *
548  * \param ul_xtal_rc 0 internal RC is selected, otherwise Main Crystal.
549  */
pmc_mainck_osc_select(uint32_t ul_xtal_rc)550 void pmc_mainck_osc_select(uint32_t ul_xtal_rc)
551 {
552 	uint32_t mor = PMC->CKGR_MOR;
553 	if (ul_xtal_rc) {
554 		mor |=  CKGR_MOR_MOSCSEL;
555 	} else {
556 		mor &= ~CKGR_MOR_MOSCSEL;
557 	}
558 	PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | mor;
559 }
560 
561 /**
562  * \brief Enable PLLA clock.
563  *
564  * \param mula PLLA multiplier.
565  * \param pllacount PLLA counter.
566  * \param diva Divider.
567  */
pmc_enable_pllack(uint32_t mula,uint32_t pllacount,uint32_t diva)568 void pmc_enable_pllack(uint32_t mula, uint32_t pllacount, uint32_t diva)
569 {
570 	/* first disable the PLL to unlock the lock */
571 	pmc_disable_pllack();
572 
573 #if (SAM4C || SAM4CM || SAM4CP || SAMG)
574 	PMC->CKGR_PLLAR = CKGR_PLLAR_PLLAEN(diva) |
575 			CKGR_PLLAR_PLLACOUNT(pllacount) | CKGR_PLLAR_MULA(mula);
576 #else
577 	PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_DIVA(diva) |
578 			CKGR_PLLAR_PLLACOUNT(pllacount) | CKGR_PLLAR_MULA(mula);
579 #endif
580 	while ((PMC->PMC_SR & PMC_SR_LOCKA) == 0);
581 }
582 
583 /**
584  * \brief Disable PLLA clock.
585  */
pmc_disable_pllack(void)586 void pmc_disable_pllack(void)
587 {
588 #if (SAM4C || SAM4CM || SAM4CP || SAMG)
589 	PMC->CKGR_PLLAR = CKGR_PLLAR_MULA(0);
590 #else
591 	PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0);
592 #endif
593 }
594 
595 /**
596  * \brief Is PLLA locked?
597  *
598  * \retval 0 Not locked.
599  * \retval 1 Locked.
600  */
pmc_is_locked_pllack(void)601 uint32_t pmc_is_locked_pllack(void)
602 {
603 	return (PMC->PMC_SR & PMC_SR_LOCKA);
604 }
605 
606 #if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP || SAMG55)
607 /**
608  * \brief Enable PLLB clock.
609  *
610  * \param mulb PLLB multiplier.
611  * \param pllbcount PLLB counter.
612  * \param divb Divider.
613  */
pmc_enable_pllbck(uint32_t mulb,uint32_t pllbcount,uint32_t divb)614 void pmc_enable_pllbck(uint32_t mulb, uint32_t pllbcount, uint32_t divb)
615 {
616 	/* first disable the PLL to unlock the lock */
617 	pmc_disable_pllbck();
618 
619 #if SAMG55
620 	PMC->CKGR_PLLAR = CKGR_PLLAR_PLLAEN(divb) |
621 		CKGR_PLLAR_PLLACOUNT(pllbcount) | CKGR_PLLAR_MULA(mulb);
622 #else
623 	PMC->CKGR_PLLBR =
624 			CKGR_PLLBR_DIVB(divb) | CKGR_PLLBR_PLLBCOUNT(pllbcount)
625 			| CKGR_PLLBR_MULB(mulb);
626 #endif
627 	while ((PMC->PMC_SR & PMC_SR_LOCKB) == 0);
628 }
629 
630 /**
631  * \brief Disable PLLB clock.
632  */
pmc_disable_pllbck(void)633 void pmc_disable_pllbck(void)
634 {
635 	PMC->CKGR_PLLBR = CKGR_PLLBR_MULB(0);
636 }
637 
638 /**
639  * \brief Is PLLB locked?
640  *
641  * \retval 0 Not locked.
642  * \retval 1 Locked.
643  */
pmc_is_locked_pllbck(void)644 uint32_t pmc_is_locked_pllbck(void)
645 {
646 	return (PMC->PMC_SR & PMC_SR_LOCKB);
647 }
648 #endif
649 
650 #if (SAM3XA || SAM3U || SAMV71 || SAMV70 || SAME70 || SAMS70)
651 /**
652  * \brief Enable UPLL clock.
653  */
pmc_enable_upll_clock(void)654 void pmc_enable_upll_clock(void)
655 {
656 	PMC->CKGR_UCKR = CKGR_UCKR_UPLLCOUNT(3) | CKGR_UCKR_UPLLEN;
657 
658 	/* Wait UTMI PLL Lock Status */
659 	while (!(PMC->PMC_SR & PMC_SR_LOCKU));
660 }
661 
662 /**
663  * \brief Disable UPLL clock.
664  */
pmc_disable_upll_clock(void)665 void pmc_disable_upll_clock(void)
666 {
667 	PMC->CKGR_UCKR &= ~CKGR_UCKR_UPLLEN;
668 }
669 
670 /**
671  * \brief Is UPLL locked?
672  *
673  * \retval 0 Not locked.
674  * \retval 1 Locked.
675  */
pmc_is_locked_upll(void)676 uint32_t pmc_is_locked_upll(void)
677 {
678 	return (PMC->PMC_SR & PMC_SR_LOCKU);
679 }
680 #endif
681 
682 /**
683  * \brief Enable the specified peripheral clock.
684  *
685  * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
686  *
687  * \param ul_id Peripheral ID (ID_xxx).
688  *
689  * \retval 0 Success.
690  * \retval 1 Invalid parameter.
691  */
pmc_enable_periph_clk(uint32_t ul_id)692 uint32_t pmc_enable_periph_clk(uint32_t ul_id)
693 {
694 	if (ul_id > MAX_PERIPH_ID) {
695 		return 1;
696 	}
697 
698 	if (ul_id < 32) {
699 		if ((PMC->PMC_PCSR0 & (1u << ul_id)) != (1u << ul_id)) {
700 			PMC->PMC_PCER0 = 1 << ul_id;
701 		}
702 #if (SAM3S || SAM3XA || SAM4S || SAM4E || SAM4C || SAM4CM || SAM4CP || SAMG55 || SAMV71 || SAMV70 || SAME70 || SAMS70)
703 	} else {
704 		ul_id -= 32;
705 		if ((PMC->PMC_PCSR1 & (1u << ul_id)) != (1u << ul_id)) {
706 			PMC->PMC_PCER1 = 1 << ul_id;
707 		}
708 #endif
709 	}
710 
711 	return 0;
712 }
713 
714 /**
715  * \brief Disable the specified peripheral clock.
716  *
717  * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
718  *
719  * \param ul_id Peripheral ID (ID_xxx).
720  *
721  * \retval 0 Success.
722  * \retval 1 Invalid parameter.
723  */
pmc_disable_periph_clk(uint32_t ul_id)724 uint32_t pmc_disable_periph_clk(uint32_t ul_id)
725 {
726 	if (ul_id > MAX_PERIPH_ID) {
727 		return 1;
728 	}
729 
730 	if (ul_id < 32) {
731 		if ((PMC->PMC_PCSR0 & (1u << ul_id)) == (1u << ul_id)) {
732 			PMC->PMC_PCDR0 = 1 << ul_id;
733 		}
734 #if (SAM3S || SAM3XA || SAM4S || SAM4E || SAM4C || SAM4CM || SAM4CP || SAMG55 || SAMV71 \
735 		|| SAMV70 || SAME70 || SAMS70)
736 	} else {
737 		ul_id -= 32;
738 		if ((PMC->PMC_PCSR1 & (1u << ul_id)) == (1u << ul_id)) {
739 			PMC->PMC_PCDR1 = 1 << ul_id;
740 		}
741 #endif
742 	}
743 	return 0;
744 }
745 
746 /**
747  * \brief Enable all peripheral clocks.
748  */
pmc_enable_all_periph_clk(void)749 void pmc_enable_all_periph_clk(void)
750 {
751 	PMC->PMC_PCER0 = PMC_MASK_STATUS0;
752 	while ((PMC->PMC_PCSR0 & PMC_MASK_STATUS0) != PMC_MASK_STATUS0);
753 
754 #if (SAM3S || SAM3XA || SAM4S || SAM4E || SAM4C || SAM4CM || SAM4CP || SAMV71  \
755 		|| SAMV70 || SAME70 || SAMS70)
756 	PMC->PMC_PCER1 = PMC_MASK_STATUS1;
757 	while ((PMC->PMC_PCSR1 & PMC_MASK_STATUS1) != PMC_MASK_STATUS1);
758 #endif
759 }
760 
761 /**
762  * \brief Disable all peripheral clocks.
763  */
pmc_disable_all_periph_clk(void)764 void pmc_disable_all_periph_clk(void)
765 {
766 	PMC->PMC_PCDR0 = PMC_MASK_STATUS0;
767 	while ((PMC->PMC_PCSR0 & PMC_MASK_STATUS0) != 0);
768 
769 #if (SAM3S || SAM3XA || SAM4S || SAM4E || SAM4C || SAM4CM || SAM4CP || SAMV71 \
770 		|| SAMV70 || SAME70 || SAMS70)
771 	PMC->PMC_PCDR1 = PMC_MASK_STATUS1;
772 	while ((PMC->PMC_PCSR1 & PMC_MASK_STATUS1) != 0);
773 #endif
774 }
775 
776 /**
777  * \brief Check if the specified peripheral clock is enabled.
778  *
779  * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
780  *
781  * \param ul_id Peripheral ID (ID_xxx).
782  *
783  * \retval 0 Peripheral clock is disabled or unknown.
784  * \retval 1 Peripheral clock is enabled.
785  */
pmc_is_periph_clk_enabled(uint32_t ul_id)786 uint32_t pmc_is_periph_clk_enabled(uint32_t ul_id)
787 {
788 	if (ul_id > MAX_PERIPH_ID) {
789 		return 0;
790 	}
791 
792 #if (SAM3S || SAM3XA || SAM4S || SAM4E || SAM4C || SAM4CM || SAM4CP || SAMV71 \
793 		|| SAMV70 || SAME70 || SAMS70)
794 	if (ul_id < 32) {
795 #endif
796 		if ((PMC->PMC_PCSR0 & (1u << ul_id))) {
797 			return 1;
798 		} else {
799 			return 0;
800 		}
801 #if (SAM3S || SAM3XA || SAM4S || SAM4E || SAM4C || SAM4CM || SAM4CP || SAMV71 \
802 		|| SAMV70 || SAME70 || SAMS70)
803 	} else {
804 		ul_id -= 32;
805 		if ((PMC->PMC_PCSR1 & (1u << ul_id))) {
806 			return 1;
807 		} else {
808 			return 0;
809 		}
810 	}
811 #endif
812 }
813 
814 /**
815  * \brief Set the prescaler for the specified programmable clock.
816  *
817  * \param ul_id Peripheral ID.
818  * \param ul_pres Prescaler value.
819  */
pmc_pck_set_prescaler(uint32_t ul_id,uint32_t ul_pres)820 void pmc_pck_set_prescaler(uint32_t ul_id, uint32_t ul_pres)
821 {
822 	PMC->PMC_PCK[ul_id] =
823 			(PMC->PMC_PCK[ul_id] & ~PMC_PCK_PRES_Msk) | ul_pres;
824 	while ((PMC->PMC_SCER & (PMC_SCER_PCK0 << ul_id))
825 			&& !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)));
826 }
827 
828 /**
829  * \brief Set the source oscillator for the specified programmable clock.
830  *
831  * \param ul_id Peripheral ID.
832  * \param ul_source Source selection value.
833  */
pmc_pck_set_source(uint32_t ul_id,uint32_t ul_source)834 void pmc_pck_set_source(uint32_t ul_id, uint32_t ul_source)
835 {
836 	PMC->PMC_PCK[ul_id] =
837 			(PMC->PMC_PCK[ul_id] & ~PMC_PCK_CSS_Msk) | ul_source;
838 	while ((PMC->PMC_SCER & (PMC_SCER_PCK0 << ul_id))
839 			&& !(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)));
840 }
841 
842 /**
843  * \brief Switch programmable clock source selection to slow clock.
844  *
845  * \param ul_id Id of the programmable clock.
846  * \param ul_pres Programmable clock prescaler.
847  *
848  * \retval 0 Success.
849  * \retval 1 Timeout error.
850  */
pmc_switch_pck_to_sclk(uint32_t ul_id,uint32_t ul_pres)851 uint32_t pmc_switch_pck_to_sclk(uint32_t ul_id, uint32_t ul_pres)
852 {
853 	uint32_t ul_timeout;
854 
855 	PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_SLOW_CLK | ul_pres;
856 	for (ul_timeout = PMC_TIMEOUT;
857 	!(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)); --ul_timeout) {
858 		if (ul_timeout == 0) {
859 			return 1;
860 		}
861 	}
862 
863 	return 0;
864 }
865 
866 /**
867  * \brief Switch programmable clock source selection to main clock.
868  *
869  * \param ul_id Id of the programmable clock.
870  * \param ul_pres Programmable clock prescaler.
871  *
872  * \retval 0 Success.
873  * \retval 1 Timeout error.
874  */
pmc_switch_pck_to_mainck(uint32_t ul_id,uint32_t ul_pres)875 uint32_t pmc_switch_pck_to_mainck(uint32_t ul_id, uint32_t ul_pres)
876 {
877 	uint32_t ul_timeout;
878 
879 	PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_MAIN_CLK | ul_pres;
880 	for (ul_timeout = PMC_TIMEOUT;
881 	!(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)); --ul_timeout) {
882 		if (ul_timeout == 0) {
883 			return 1;
884 		}
885 	}
886 
887 	return 0;
888 }
889 
890 /**
891  * \brief Switch programmable clock source selection to PLLA clock.
892  *
893  * \param ul_id Id of the programmable clock.
894  * \param ul_pres Programmable clock prescaler.
895  *
896  * \retval 0 Success.
897  * \retval 1 Timeout error.
898  */
pmc_switch_pck_to_pllack(uint32_t ul_id,uint32_t ul_pres)899 uint32_t pmc_switch_pck_to_pllack(uint32_t ul_id, uint32_t ul_pres)
900 {
901 	uint32_t ul_timeout;
902 
903 	PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_PLLA_CLK | ul_pres;
904 	for (ul_timeout = PMC_TIMEOUT;
905 	!(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)); --ul_timeout) {
906 		if (ul_timeout == 0) {
907 			return 1;
908 		}
909 	}
910 
911 	return 0;
912 }
913 
914 #if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP || SAMG55)
915 /**
916  * \brief Switch programmable clock source selection to PLLB clock.
917  *
918  * \param ul_id Id of the programmable clock.
919  * \param ul_pres Programmable clock prescaler.
920  *
921  * \retval 0 Success.
922  * \retval 1 Timeout error.
923  */
pmc_switch_pck_to_pllbck(uint32_t ul_id,uint32_t ul_pres)924 uint32_t pmc_switch_pck_to_pllbck(uint32_t ul_id, uint32_t ul_pres)
925 {
926 	uint32_t ul_timeout;
927 
928 	PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_PLLB_CLK | ul_pres;
929 	for (ul_timeout = PMC_TIMEOUT;
930 			!(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id));
931 			--ul_timeout) {
932 		if (ul_timeout == 0) {
933 			return 1;
934 		}
935 	}
936 
937 	return 0;
938 }
939 #endif
940 
941 #if (SAM3XA || SAM3U || SAMV71 || SAMV70 || SAME70 || SAMS70)
942 /**
943  * \brief Switch programmable clock source selection to UPLL clock.
944  *
945  * \param ul_id Id of the programmable clock.
946  * \param ul_pres Programmable clock prescaler.
947  *
948  * \retval 0 Success.
949  * \retval 1 Timeout error.
950  */
pmc_switch_pck_to_upllck(uint32_t ul_id,uint32_t ul_pres)951 uint32_t pmc_switch_pck_to_upllck(uint32_t ul_id, uint32_t ul_pres)
952 {
953 	uint32_t ul_timeout;
954 
955 	PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_UPLL_CLK | ul_pres;
956 	for (ul_timeout = PMC_TIMEOUT;
957 			!(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id));
958 			--ul_timeout) {
959 		if (ul_timeout == 0) {
960 			return 1;
961 		}
962 	}
963 
964 	return 0;
965 }
966 #endif
967 
968 /**
969  * \brief Switch programmable clock source selection to mck.
970  *
971  * \param ul_id Id of the programmable clock.
972  * \param ul_pres Programmable clock prescaler.
973  *
974  * \retval 0 Success.
975  * \retval 1 Timeout error.
976  */
pmc_switch_pck_to_mck(uint32_t ul_id,uint32_t ul_pres)977 uint32_t pmc_switch_pck_to_mck(uint32_t ul_id, uint32_t ul_pres)
978 {
979 	uint32_t ul_timeout;
980 
981 	PMC->PMC_PCK[ul_id] = PMC_PCK_CSS_MCK | ul_pres;
982 	for (ul_timeout = PMC_TIMEOUT;
983 	!(PMC->PMC_SR & (PMC_SR_PCKRDY0 << ul_id)); --ul_timeout) {
984 		if (ul_timeout == 0) {
985 			return 1;
986 		}
987 	}
988 
989 	return 0;
990 }
991 
992 /**
993  * \brief Enable the specified programmable clock.
994  *
995  * \param ul_id Id of the programmable clock.
996  */
pmc_enable_pck(uint32_t ul_id)997 void pmc_enable_pck(uint32_t ul_id)
998 {
999 	PMC->PMC_SCER = PMC_SCER_PCK0 << ul_id;
1000 }
1001 
1002 /**
1003  * \brief Disable the specified programmable clock.
1004  *
1005  * \param ul_id Id of the programmable clock.
1006  */
pmc_disable_pck(uint32_t ul_id)1007 void pmc_disable_pck(uint32_t ul_id)
1008 {
1009 	PMC->PMC_SCDR = PMC_SCER_PCK0 << ul_id;
1010 }
1011 
1012 /**
1013  * \brief Enable all programmable clocks.
1014  */
pmc_enable_all_pck(void)1015 void pmc_enable_all_pck(void)
1016 {
1017 	PMC->PMC_SCER = PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2;
1018 }
1019 
1020 /**
1021  * \brief Disable all programmable clocks.
1022  */
pmc_disable_all_pck(void)1023 void pmc_disable_all_pck(void)
1024 {
1025 	PMC->PMC_SCDR = PMC_SCDR_PCK0 | PMC_SCDR_PCK1 | PMC_SCDR_PCK2;
1026 }
1027 
1028 /**
1029  * \brief Check if the specified programmable clock is enabled.
1030  *
1031  * \param ul_id Id of the programmable clock.
1032  *
1033  * \retval 0 Programmable clock is disabled or unknown.
1034  * \retval 1 Programmable clock is enabled.
1035  */
pmc_is_pck_enabled(uint32_t ul_id)1036 uint32_t pmc_is_pck_enabled(uint32_t ul_id)
1037 {
1038 	if (ul_id > 2) {
1039 		return 0;
1040 	}
1041 
1042 	return (PMC->PMC_SCSR & (PMC_SCSR_PCK0 << ul_id));
1043 }
1044 
1045 #if (SAM4C || SAM4CM || SAM4CP)
1046 /**
1047  * \brief Enable Coprocessor Clocks.
1048  */
pmc_enable_cpck(void)1049 void pmc_enable_cpck(void)
1050 {
1051 	PMC->PMC_SCER = PMC_SCER_CPCK | PMC_SCER_CPKEY_PASSWD;
1052 }
1053 
1054 /**
1055  * \brief Disable Coprocessor Clocks.
1056  */
pmc_disable_cpck(void)1057 void pmc_disable_cpck(void)
1058 {
1059 	PMC->PMC_SCDR = PMC_SCDR_CPCK | PMC_SCDR_CPKEY_PASSWD;
1060 }
1061 
1062 /**
1063  * \brief Check if the Coprocessor Clocks is enabled.
1064  *
1065  * \retval 0 Coprocessor Clocks is disabled.
1066  * \retval 1 Coprocessor Clocks is enabled.
1067  */
pmc_is_cpck_enabled(void)1068 bool pmc_is_cpck_enabled(void)
1069 {
1070 	if(PMC->PMC_SCSR & PMC_SCSR_CPCK) {
1071 		return 1;
1072 	} else {
1073 		return 0;
1074 	}
1075 }
1076 
1077 /**
1078  * \brief Enable Coprocessor Bus Master Clocks.
1079  */
pmc_enable_cpbmck(void)1080 void pmc_enable_cpbmck(void)
1081 {
1082 	PMC->PMC_SCER = PMC_SCER_CPCK | PMC_SCER_CPKEY_PASSWD;
1083 }
1084 
1085 /**
1086  * \brief Disable Coprocessor Bus Master Clocks.
1087  */
pmc_disable_cpbmck(void)1088 void pmc_disable_cpbmck(void)
1089 {
1090 	PMC->PMC_SCDR = PMC_SCDR_CPCK | PMC_SCDR_CPKEY_PASSWD;
1091 }
1092 
1093 /**
1094  * \brief Check if the Coprocessor Bus Master Clocks is enabled.
1095  *
1096  * \retval 0 Coprocessor Bus Master Clocks is disabled.
1097  * \retval 1 Coprocessor Bus Master Clocks is enabled.
1098  */
pmc_is_cpbmck_enabled(void)1099 bool pmc_is_cpbmck_enabled(void)
1100 {
1101 	if(PMC->PMC_SCSR & PMC_SCSR_CPBMCK) {
1102 		return 1;
1103 	} else {
1104 		return 0;
1105 	}
1106 }
1107 
1108 /**
1109  * \brief Set the prescaler for the Coprocessor Master Clock.
1110  *
1111  * \param ul_pres Prescaler value.
1112  */
pmc_cpck_set_prescaler(uint32_t ul_pres)1113 void pmc_cpck_set_prescaler(uint32_t ul_pres)
1114 {
1115 	PMC->PMC_MCKR =
1116 			(PMC->PMC_MCKR & (~PMC_MCKR_CPPRES_Msk)) | PMC_MCKR_CPPRES(ul_pres);
1117 }
1118 
1119 /**
1120  * \brief Set the source for the Coprocessor Master Clock.
1121  *
1122  * \param ul_source Source selection value.
1123  */
pmc_cpck_set_source(uint32_t ul_source)1124 void pmc_cpck_set_source(uint32_t ul_source)
1125 {
1126 	PMC->PMC_MCKR =
1127 			(PMC->PMC_MCKR & (~PMC_MCKR_CPCSS_Msk)) | ul_source;
1128 }
1129 #endif
1130 
1131 #if (SAM3S || SAM3XA || SAM4S || SAM4E || SAMG55 || SAMV71 || SAMV70 || SAME70 || SAMS70)
1132 /**
1133  * \brief Switch UDP (USB) clock source selection to PLLA clock.
1134  *
1135  * \param ul_usbdiv Clock divisor.
1136  */
pmc_switch_udpck_to_pllack(uint32_t ul_usbdiv)1137 void pmc_switch_udpck_to_pllack(uint32_t ul_usbdiv)
1138 {
1139 	PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv);
1140 }
1141 #endif
1142 
1143 #if (SAM3S || SAM4S || SAMG55)
1144 /**
1145  * \brief Switch UDP (USB) clock source selection to PLLB clock.
1146  *
1147  * \param ul_usbdiv Clock divisor.
1148  */
pmc_switch_udpck_to_pllbck(uint32_t ul_usbdiv)1149 void pmc_switch_udpck_to_pllbck(uint32_t ul_usbdiv)
1150 {
1151 	PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv) | PMC_USB_USBS;
1152 }
1153 #endif
1154 
1155 #if (SAM3XA || SAMV71 || SAMV70 || SAME70 || SAMS70)
1156 /**
1157  * \brief Switch UDP (USB) clock source selection to UPLL clock.
1158  *
1159  * \param ul_usbdiv Clock divisor.
1160  */
pmc_switch_udpck_to_upllck(uint32_t ul_usbdiv)1161 void pmc_switch_udpck_to_upllck(uint32_t ul_usbdiv)
1162 {
1163 	PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(ul_usbdiv);
1164 }
1165 #endif
1166 
1167 #if (SAM3S || SAM3XA || SAM4S || SAM4E || SAMG55 || SAMV71 || SAMV70 || SAME70 || SAMS70)
1168 /**
1169  * \brief Enable UDP (USB) clock.
1170  */
pmc_enable_udpck(void)1171 void pmc_enable_udpck(void)
1172 {
1173 #if (SAM3S || SAM4S || SAM4E || SAMG55)
1174 	PMC->PMC_SCER = PMC_SCER_UDP;
1175 #elif (SAMV71 || SAMV70 || SAME70 || SAMS70)
1176 	PMC->PMC_SCER = PMC_SCER_USBCLK;
1177 #else
1178 	PMC->PMC_SCER = PMC_SCER_UOTGCLK;
1179 # endif
1180 }
1181 
1182 /**
1183  * \brief Disable UDP (USB) clock.
1184  */
pmc_disable_udpck(void)1185 void pmc_disable_udpck(void)
1186 {
1187 #if (SAM3S || SAM4S || SAM4E || SAMG55)
1188 	PMC->PMC_SCDR = PMC_SCDR_UDP;
1189 #elif (SAMV71 || SAMV70 || SAME70 || SAMS70)
1190 	PMC->PMC_SCDR = PMC_SCDR_USBCLK;
1191 #else
1192 	PMC->PMC_SCDR = PMC_SCDR_UOTGCLK;
1193 # endif
1194 }
1195 #endif
1196 
1197 #if SAMG55
1198 /**
1199  * \brief Switch UHP (USB) clock source selection to PLLA clock.
1200  *
1201  * \param ul_usbdiv Clock divisor.
1202  */
pmc_switch_uhpck_to_pllack(uint32_t ul_usbdiv)1203 void pmc_switch_uhpck_to_pllack(uint32_t ul_usbdiv)
1204 {
1205 	PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv);
1206 }
1207 
1208 /**
1209  * \brief Switch UHP (USB) clock source selection to PLLB clock.
1210  *
1211  * \param ul_usbdiv Clock divisor.
1212  */
pmc_switch_uhpck_to_pllbck(uint32_t ul_usbdiv)1213 void pmc_switch_uhpck_to_pllbck(uint32_t ul_usbdiv)
1214 {
1215 	PMC->PMC_USB = PMC_USB_USBDIV(ul_usbdiv) | PMC_USB_USBS;
1216 }
1217 
1218 /**
1219  * \brief Enable UHP (USB) clock.
1220  */
pmc_enable_uhpck(void)1221 void pmc_enable_uhpck(void)
1222 {
1223 	PMC->PMC_SCER = PMC_SCER_UHP;
1224 }
1225 #endif
1226 
1227 /**
1228  * \brief Enable PMC interrupts.
1229  *
1230  * \param ul_sources Interrupt sources bit map.
1231  */
pmc_enable_interrupt(uint32_t ul_sources)1232 void pmc_enable_interrupt(uint32_t ul_sources)
1233 {
1234 	PMC->PMC_IER = ul_sources;
1235 }
1236 
1237 /**
1238  * \brief Disable PMC interrupts.
1239  *
1240  * \param ul_sources Interrupt sources bit map.
1241  */
pmc_disable_interrupt(uint32_t ul_sources)1242 void pmc_disable_interrupt(uint32_t ul_sources)
1243 {
1244 	PMC->PMC_IDR = ul_sources;
1245 }
1246 
1247 /**
1248  * \brief Get PMC interrupt mask.
1249  *
1250  * \return The interrupt mask value.
1251  */
pmc_get_interrupt_mask(void)1252 uint32_t pmc_get_interrupt_mask(void)
1253 {
1254 	return PMC->PMC_IMR;
1255 }
1256 
1257 /**
1258  * \brief Get current status.
1259  *
1260  * \return The current PMC status.
1261  */
pmc_get_status(void)1262 uint32_t pmc_get_status(void)
1263 {
1264 	return PMC->PMC_SR;
1265 }
1266 
1267 /**
1268  * \brief Set the wake-up inputs for fast startup mode registers
1269  *        (event generation).
1270  *
1271  * \param ul_inputs Wake up inputs to enable.
1272  */
pmc_set_fast_startup_input(uint32_t ul_inputs)1273 void pmc_set_fast_startup_input(uint32_t ul_inputs)
1274 {
1275 	ul_inputs &= PMC_FAST_STARTUP_Msk;
1276 	PMC->PMC_FSMR |= ul_inputs;
1277 }
1278 
1279 /**
1280  * \brief Clear the wake-up inputs for fast startup mode registers
1281  *        (remove event generation).
1282  *
1283  * \param ul_inputs Wake up inputs to disable.
1284  */
pmc_clr_fast_startup_input(uint32_t ul_inputs)1285 void pmc_clr_fast_startup_input(uint32_t ul_inputs)
1286 {
1287 	ul_inputs &= PMC_FAST_STARTUP_Msk;
1288 	PMC->PMC_FSMR &= ~ul_inputs;
1289 }
1290 
1291 #if (SAM4C || SAM4CM || SAM4CP)
1292 /**
1293  * \brief Set the wake-up inputs of coprocessor for fast startup mode registers
1294  *        (event generation).
1295  *
1296  * \param ul_inputs Wake up inputs to enable.
1297  */
pmc_cp_set_fast_startup_input(uint32_t ul_inputs)1298 void pmc_cp_set_fast_startup_input(uint32_t ul_inputs)
1299 {
1300 	ul_inputs &= PMC_FAST_STARTUP_Msk;
1301 	PMC->PMC_CPFSMR |= ul_inputs;
1302 }
1303 
1304 /**
1305  * \brief Clear the wake-up inputs of coprocessor for fast startup mode registers
1306  *        (remove event generation).
1307  *
1308  * \param ul_inputs Wake up inputs to disable.
1309  */
pmc_cp_clr_fast_startup_input(uint32_t ul_inputs)1310 void pmc_cp_clr_fast_startup_input(uint32_t ul_inputs)
1311 {
1312 	ul_inputs &= PMC_FAST_STARTUP_Msk;
1313 	PMC->PMC_CPFSMR &= ~ul_inputs;
1314 }
1315 #endif
1316 
1317 #if (!(SAMG51 || SAMG53 || SAMG54))
1318 /**
1319  * \brief Enable Sleep Mode.
1320  * Enter condition: (WFE or WFI) + (SLEEPDEEP bit = 0) + (LPM bit = 0)
1321  *
1322  * \param uc_type 0 for wait for interrupt, 1 for wait for event.
1323  * \note For SAM4S, SAM4C, SAM4CM, SAM4CP, SAMV71 and SAM4E series,
1324  * since only WFI is effective, uc_type = 1 will be treated as uc_type = 0.
1325  */
pmc_enable_sleepmode(uint8_t uc_type)1326 void pmc_enable_sleepmode(uint8_t uc_type)
1327 {
1328 #if !(SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAM4CP || SAMV71 || SAMV70 || SAME70 || SAMS70)
1329 	PMC->PMC_FSMR &= (uint32_t) ~ PMC_FSMR_LPM; // Enter Sleep mode
1330 #endif
1331 	SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk; // Deep sleep
1332 
1333 #if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAM4CP || SAMV71 || SAMV70 || SAME70 || SAMS70)
1334 	UNUSED(uc_type);
1335 	__WFI();
1336 #else
1337 	if (uc_type == 0) {
1338 		__WFI();
1339 	} else {
1340 		__WFE();
1341 	}
1342 #endif
1343 }
1344 #endif
1345 
1346 #if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAMG || SAM4CP || SAMV71 || SAMV70 || SAME70 || SAMS70)
1347 static uint32_t ul_flash_in_wait_mode = PMC_WAIT_MODE_FLASH_DEEP_POWERDOWN;
1348 /**
1349  * \brief Set the embedded flash state in wait mode
1350  *
1351  * \param ul_flash_state PMC_WAIT_MODE_FLASH_STANDBY flash in standby mode,
1352  * PMC_WAIT_MODE_FLASH_DEEP_POWERDOWN flash in deep power down mode.
1353  */
pmc_set_flash_in_wait_mode(uint32_t ul_flash_state)1354 void pmc_set_flash_in_wait_mode(uint32_t ul_flash_state)
1355 {
1356 	ul_flash_in_wait_mode = ul_flash_state;
1357 }
1358 
1359 /**
1360  * \brief Enable Wait Mode. Enter condition: (WAITMODE bit = 1) + FLPM
1361  *
1362  * \note In this function, FLPM will retain, WAITMODE bit will be set,
1363  * Generally, this function will be called by pmc_sleep() in order to
1364  * complete all sequence entering wait mode.
1365  * See \ref pmc_sleep() for entering different sleep modes.
1366  */
pmc_enable_waitmode(void)1367 void pmc_enable_waitmode(void)
1368 {
1369 	uint32_t i;
1370 
1371 	/* Flash in wait mode */
1372 	i = PMC->PMC_FSMR;
1373 	i &= ~PMC_FSMR_FLPM_Msk;
1374 	i |= ul_flash_in_wait_mode;
1375 	PMC->PMC_FSMR = i;
1376 
1377 	/* Set the WAITMODE bit = 1 */
1378 	PMC->CKGR_MOR |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_WAITMODE;
1379 
1380 	/* Waiting for Master Clock Ready MCKRDY = 1 */
1381 	while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
1382 
1383 	/* Waiting for MOSCRCEN bit cleared is strongly recommended
1384 	 * to ensure that the core will not execute undesired instructions
1385 	 */
1386 	for (i = 0; i < 500; i++) {
1387 		__NOP();
1388 	}
1389 	while (!(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN));
1390 
1391 #if (!SAMG)
1392 	/* Restore Flash in idle mode */
1393 	i = PMC->PMC_FSMR;
1394 	i &= ~PMC_FSMR_FLPM_Msk;
1395 	i |= PMC_WAIT_MODE_FLASH_IDLE;
1396 	PMC->PMC_FSMR = i;
1397 #endif
1398 }
1399 #else
1400 /**
1401  * \brief Enable Wait Mode. Enter condition: WFE + (SLEEPDEEP bit = 0) +
1402  * (LPM bit = 1)
1403  */
pmc_enable_waitmode(void)1404 void pmc_enable_waitmode(void)
1405 {
1406 	uint32_t i;
1407 
1408 	PMC->PMC_FSMR |= PMC_FSMR_LPM; /* Enter Wait mode */
1409 	SCB->SCR &= (uint32_t) ~ SCB_SCR_SLEEPDEEP_Msk; /* Deep sleep */
1410 
1411 	__WFE();
1412 
1413 	/* Waiting for MOSCRCEN bit cleared is strongly recommended
1414 	 * to ensure that the core will not execute undesired instructions
1415 	 */
1416 	for (i = 0; i < 500; i++) {
1417 		__NOP();
1418 	}
1419 	while (!(PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN));
1420 
1421 }
1422 #endif
1423 
1424 #if (!(SAMG51 || SAMG53 || SAMG54))
1425 /**
1426  * \brief Enable Backup Mode. Enter condition: WFE/(VROFF bit = 1) +
1427  * (SLEEPDEEP bit = 1)
1428  */
pmc_enable_backupmode(void)1429 void pmc_enable_backupmode(void)
1430 {
1431 #if (SAM4C || SAM4CM || SAM4CP)
1432 	uint32_t tmp = SUPC->SUPC_MR & ~(SUPC_MR_BUPPOREN | SUPC_MR_KEY_Msk);
1433 	SUPC->SUPC_MR = tmp | SUPC_MR_KEY_PASSWD;
1434 	while (SUPC->SUPC_SR & SUPC_SR_BUPPORS);
1435 #endif
1436 	SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
1437 #if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAM4CP || SAMG55 || SAMV71 || SAMV70 || SAME70 || SAMS70)
1438 	SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_VROFF_STOP_VREG;
1439 	__WFE();
1440 	__WFI();
1441 #else
1442 	__WFE();
1443 #endif
1444 }
1445 #endif
1446 
1447 /**
1448  * \brief Enable Clock Failure Detector.
1449  */
pmc_enable_clock_failure_detector(void)1450 void pmc_enable_clock_failure_detector(void)
1451 {
1452 	uint32_t ul_reg = PMC->CKGR_MOR;
1453 
1454 	PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | CKGR_MOR_CFDEN | ul_reg;
1455 }
1456 
1457 /**
1458  * \brief Disable Clock Failure Detector.
1459  */
pmc_disable_clock_failure_detector(void)1460 void pmc_disable_clock_failure_detector(void)
1461 {
1462 	uint32_t ul_reg = PMC->CKGR_MOR & (~CKGR_MOR_CFDEN);
1463 
1464 	PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | ul_reg;
1465 }
1466 
1467 #if (SAM4N || SAM4C || SAM4CM || SAM4CP || SAMV71 || SAMV70 || SAME70 || SAMS70)
1468 /**
1469  * \brief Enable Slow Crystal Oscillator Frequency Monitoring.
1470  */
pmc_enable_sclk_osc_freq_monitor(void)1471 void pmc_enable_sclk_osc_freq_monitor(void)
1472 {
1473 	uint32_t ul_reg = PMC->CKGR_MOR;
1474 
1475 	PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | CKGR_MOR_XT32KFME | ul_reg;
1476 }
1477 
1478 /**
1479  * \brief Disable Slow Crystal Oscillator Frequency Monitoring.
1480  */
pmc_disable_sclk_osc_freq_monitor(void)1481 void pmc_disable_sclk_osc_freq_monitor(void)
1482 {
1483 	uint32_t ul_reg = PMC->CKGR_MOR & (~CKGR_MOR_XT32KFME);
1484 
1485 	PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | ul_reg;
1486 }
1487 #endif
1488 
1489 /**
1490  * \brief Enable or disable write protect of PMC registers.
1491  *
1492  * \param ul_enable 1 to enable, 0 to disable.
1493  */
pmc_set_writeprotect(uint32_t ul_enable)1494 void pmc_set_writeprotect(uint32_t ul_enable)
1495 {
1496 	if (ul_enable) {
1497 		PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD | PMC_WPMR_WPEN;
1498 	} else {
1499 		PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD;
1500 	}
1501 }
1502 
1503 /**
1504  * \brief Return write protect status.
1505  *
1506  * \return Return write protect status.
1507  */
pmc_get_writeprotect_status(void)1508 uint32_t pmc_get_writeprotect_status(void)
1509 {
1510 	return PMC->PMC_WPSR;
1511 }
1512 
1513 #if (SAMG53 || SAMG54 || SAMG55 || SAMV71 || SAMV70 || SAME70 || SAMS70)
1514 /**
1515  * \brief Enable the specified peripheral clock.
1516  *
1517  * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
1518  *
1519  * \param ul_id Peripheral ID (ID_xxx).
1520  *
1521  * \retval 0 Success.
1522  * \retval 1 Fail.
1523  */
pmc_enable_sleepwalking(uint32_t ul_id)1524 uint32_t pmc_enable_sleepwalking(uint32_t ul_id)
1525 {
1526 	uint32_t temp;
1527 #if (SAMG55 || SAMV71 || SAMV70 || SAME70 || SAMS70)
1528 	if ((7 <= ul_id) && (ul_id<= 29)) {
1529 #else
1530 	if ((8 <= ul_id) && (ul_id<= 29)) {
1531 #endif
1532 		temp = pmc_get_active_status0();
1533 		if (temp & (1 << ul_id)) {
1534 			return 1;
1535 		}
1536 		PMC->PMC_SLPWK_ER0 = 1 << ul_id;
1537 		temp = pmc_get_active_status0();
1538 		if (temp & (1 << ul_id)) {
1539 			pmc_disable_sleepwalking(ul_id);
1540 			return 1;
1541 		}
1542 		return 0;
1543 	}
1544 #if (SAMV71 || SAMV70 || SAME70 || SAMS70)
1545 	else if ((32 <= ul_id) && (ul_id<= 60)) {
1546 		ul_id -= 32;
1547 		temp = pmc_get_active_status1();
1548 		if (temp & (1 << ul_id)) {
1549 			return 1;
1550 		}
1551 		PMC->PMC_SLPWK_ER1 = 1 << ul_id;
1552 		temp = pmc_get_active_status1();
1553 		if (temp & (1 << ul_id)) {
1554 			pmc_disable_sleepwalking(ul_id);
1555 			return 1;
1556 		}
1557 		return 0;
1558 	}
1559 #endif
1560 	else {
1561 		return 1;
1562 	}
1563 }
1564 
1565 /**
1566  * \brief Disable the sleepwalking of specified peripheral.
1567  *
1568  * \note The ID must NOT be shifted (i.e., 1 << ID_xxx).
1569  *
1570  * \param ul_id Peripheral ID (ID_xxx).
1571  *
1572  * \retval 0 Success.
1573  * \retval 1 Invalid parameter.
1574  */
1575 uint32_t pmc_disable_sleepwalking(uint32_t ul_id)
1576 {
1577 #if (SAMG55 || SAMV71 || SAMV70 || SAME70 || SAMS70)
1578 	if ((7 <= ul_id) && (ul_id<= 29)) {
1579 #else
1580 	if ((8 <= ul_id) && (ul_id<= 29)) {
1581 #endif
1582 		PMC->PMC_SLPWK_DR0 = 1 << ul_id;
1583 		return 0;
1584 	}
1585 #if (SAMV71 || SAMV70 || SAME70 || SAMS70)
1586 	else if ((32 <= ul_id) && (ul_id<= 60)) {
1587 		ul_id -= 32;
1588 		PMC->PMC_SLPWK_DR1 = 1 << ul_id;
1589 		return 0;
1590 	}
1591 #endif
1592 	else {
1593 		return 1;
1594 	}
1595 }
1596 
1597 /**
1598  * \brief Return peripheral sleepwalking enable status.
1599  *
1600  * \return the status register value.
1601  */
1602 uint32_t pmc_get_sleepwalking_status0(void)
1603 {
1604 	return PMC->PMC_SLPWK_SR0;
1605 }
1606 
1607 /**
1608  * \brief Return peripheral active status.
1609  *
1610  * \return the status register value.
1611  */
1612 uint32_t pmc_get_active_status0(void)
1613 {
1614 	return PMC->PMC_SLPWK_ASR0;
1615 }
1616 
1617 #endif
1618 
1619 #if (SAMV71 || SAMV70 || SAME70 || SAMS70)
1620 /**
1621  * \brief Return peripheral sleepwalking enable status.
1622  *
1623  * \return the status register value.
1624  */
1625 uint32_t pmc_get_sleepwalking_status1(void)
1626 {
1627 	return PMC->PMC_SLPWK_SR1;
1628 }
1629 
1630 /**
1631  * \brief Return peripheral active status.
1632  *
1633  * \return the status register value.
1634  */
1635 uint32_t pmc_get_active_status1(void)
1636 {
1637 	return PMC->PMC_SLPWK_ASR1;
1638 }
1639 #endif
1640 
1641 /// @cond 0
1642 /**INDENT-OFF**/
1643 #ifdef __cplusplus
1644 }
1645 #endif
1646 /**INDENT-ON**/
1647 /// @endcond
1648