1*1b2596b5SMatthias Ringwald /**
2*1b2596b5SMatthias Ringwald * \file
3*1b2596b5SMatthias Ringwald *
4*1b2596b5SMatthias Ringwald * \brief Sleep mode access
5*1b2596b5SMatthias Ringwald *
6*1b2596b5SMatthias Ringwald * Copyright (c) 2012-2015 Atmel Corporation. All rights reserved.
7*1b2596b5SMatthias Ringwald *
8*1b2596b5SMatthias Ringwald * \asf_license_start
9*1b2596b5SMatthias Ringwald *
10*1b2596b5SMatthias Ringwald * \page License
11*1b2596b5SMatthias Ringwald *
12*1b2596b5SMatthias Ringwald * Redistribution and use in source and binary forms, with or without
13*1b2596b5SMatthias Ringwald * modification, are permitted provided that the following conditions are met:
14*1b2596b5SMatthias Ringwald *
15*1b2596b5SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright notice,
16*1b2596b5SMatthias Ringwald * this list of conditions and the following disclaimer.
17*1b2596b5SMatthias Ringwald *
18*1b2596b5SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright notice,
19*1b2596b5SMatthias Ringwald * this list of conditions and the following disclaimer in the documentation
20*1b2596b5SMatthias Ringwald * and/or other materials provided with the distribution.
21*1b2596b5SMatthias Ringwald *
22*1b2596b5SMatthias Ringwald * 3. The name of Atmel may not be used to endorse or promote products derived
23*1b2596b5SMatthias Ringwald * from this software without specific prior written permission.
24*1b2596b5SMatthias Ringwald *
25*1b2596b5SMatthias Ringwald * 4. This software may only be redistributed and used in connection with an
26*1b2596b5SMatthias Ringwald * Atmel microcontroller product.
27*1b2596b5SMatthias Ringwald *
28*1b2596b5SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29*1b2596b5SMatthias Ringwald * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30*1b2596b5SMatthias Ringwald * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31*1b2596b5SMatthias Ringwald * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32*1b2596b5SMatthias Ringwald * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33*1b2596b5SMatthias Ringwald * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34*1b2596b5SMatthias Ringwald * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35*1b2596b5SMatthias Ringwald * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36*1b2596b5SMatthias Ringwald * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37*1b2596b5SMatthias Ringwald * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38*1b2596b5SMatthias Ringwald * POSSIBILITY OF SUCH DAMAGE.
39*1b2596b5SMatthias Ringwald *
40*1b2596b5SMatthias Ringwald * \asf_license_stop
41*1b2596b5SMatthias Ringwald *
42*1b2596b5SMatthias Ringwald */
43*1b2596b5SMatthias Ringwald /*
44*1b2596b5SMatthias Ringwald * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45*1b2596b5SMatthias Ringwald */
46*1b2596b5SMatthias Ringwald
47*1b2596b5SMatthias Ringwald #include <compiler.h>
48*1b2596b5SMatthias Ringwald #include "sleep.h"
49*1b2596b5SMatthias Ringwald
50*1b2596b5SMatthias Ringwald /* SAM3 and SAM4 series */
51*1b2596b5SMatthias Ringwald #if (SAM3S || SAM3N || SAM3XA || SAM3U || SAM4S || SAM4E || SAM4N || SAM4C || \
52*1b2596b5SMatthias Ringwald SAM4CM || SAMG || SAM4CP || SAMV71 || SAMV70 || SAMS70 || SAME70)
53*1b2596b5SMatthias Ringwald # include "pmc.h"
54*1b2596b5SMatthias Ringwald # include "board.h"
55*1b2596b5SMatthias Ringwald
56*1b2596b5SMatthias Ringwald /* Checking board configuration of main clock xtal statup time */
57*1b2596b5SMatthias Ringwald #if !defined(BOARD_OSC_STARTUP_US)
58*1b2596b5SMatthias Ringwald # warning The board main clock xtal statup time has not been defined. Using default settings.
59*1b2596b5SMatthias Ringwald # define BOARD_OSC_STARTUP_US (15625UL)
60*1b2596b5SMatthias Ringwald #endif
61*1b2596b5SMatthias Ringwald
62*1b2596b5SMatthias Ringwald #if !defined(EFC0)
63*1b2596b5SMatthias Ringwald # define EFC0 EFC
64*1b2596b5SMatthias Ringwald #endif
65*1b2596b5SMatthias Ringwald
66*1b2596b5SMatthias Ringwald /**
67*1b2596b5SMatthias Ringwald * Save clock settings and shutdown PLLs
68*1b2596b5SMatthias Ringwald */
pmc_save_clock_settings(uint32_t * p_osc_setting,uint32_t * p_pll0_setting,uint32_t * p_pll1_setting,uint32_t * p_mck_setting,uint32_t * p_fmr_setting,uint32_t * p_fmr_setting1,const bool disable_xtal)69*1b2596b5SMatthias Ringwald __always_inline static void pmc_save_clock_settings(
70*1b2596b5SMatthias Ringwald uint32_t *p_osc_setting,
71*1b2596b5SMatthias Ringwald uint32_t *p_pll0_setting,
72*1b2596b5SMatthias Ringwald uint32_t *p_pll1_setting,
73*1b2596b5SMatthias Ringwald uint32_t *p_mck_setting,
74*1b2596b5SMatthias Ringwald uint32_t *p_fmr_setting,
75*1b2596b5SMatthias Ringwald #if defined(EFC1)
76*1b2596b5SMatthias Ringwald uint32_t *p_fmr_setting1,
77*1b2596b5SMatthias Ringwald #endif
78*1b2596b5SMatthias Ringwald const bool disable_xtal)
79*1b2596b5SMatthias Ringwald {
80*1b2596b5SMatthias Ringwald uint32_t mor = PMC->CKGR_MOR;
81*1b2596b5SMatthias Ringwald uint32_t mckr = PMC->PMC_MCKR;
82*1b2596b5SMatthias Ringwald uint32_t fmr = EFC0->EEFC_FMR;
83*1b2596b5SMatthias Ringwald # if defined(EFC1)
84*1b2596b5SMatthias Ringwald uint32_t fmr1 = EFC1->EEFC_FMR;
85*1b2596b5SMatthias Ringwald # endif
86*1b2596b5SMatthias Ringwald
87*1b2596b5SMatthias Ringwald if (p_osc_setting) {
88*1b2596b5SMatthias Ringwald *p_osc_setting = mor;
89*1b2596b5SMatthias Ringwald }
90*1b2596b5SMatthias Ringwald if (p_pll0_setting) {
91*1b2596b5SMatthias Ringwald *p_pll0_setting = PMC->CKGR_PLLAR;
92*1b2596b5SMatthias Ringwald }
93*1b2596b5SMatthias Ringwald if (p_pll1_setting) {
94*1b2596b5SMatthias Ringwald #if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)
95*1b2596b5SMatthias Ringwald *p_pll1_setting = PMC->CKGR_PLLBR;
96*1b2596b5SMatthias Ringwald #elif (SAM3U || SAM3XA)
97*1b2596b5SMatthias Ringwald *p_pll1_setting = PMC->CKGR_UCKR;
98*1b2596b5SMatthias Ringwald #else
99*1b2596b5SMatthias Ringwald *p_pll1_setting = 0;
100*1b2596b5SMatthias Ringwald #endif
101*1b2596b5SMatthias Ringwald }
102*1b2596b5SMatthias Ringwald if (p_mck_setting) {
103*1b2596b5SMatthias Ringwald *p_mck_setting = mckr;
104*1b2596b5SMatthias Ringwald }
105*1b2596b5SMatthias Ringwald if (p_fmr_setting) {
106*1b2596b5SMatthias Ringwald *p_fmr_setting = fmr;
107*1b2596b5SMatthias Ringwald }
108*1b2596b5SMatthias Ringwald #if defined(EFC1)
109*1b2596b5SMatthias Ringwald if (p_fmr_setting1) {
110*1b2596b5SMatthias Ringwald *p_fmr_setting1 = fmr1;
111*1b2596b5SMatthias Ringwald }
112*1b2596b5SMatthias Ringwald #endif
113*1b2596b5SMatthias Ringwald
114*1b2596b5SMatthias Ringwald /* Enable FAST RC */
115*1b2596b5SMatthias Ringwald PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | mor | CKGR_MOR_MOSCRCEN;
116*1b2596b5SMatthias Ringwald /* if MCK source is PLL, switch to mainck */
117*1b2596b5SMatthias Ringwald if ((mckr & PMC_MCKR_CSS_Msk) > PMC_MCKR_CSS_MAIN_CLK) {
118*1b2596b5SMatthias Ringwald /* MCK -> MAINCK */
119*1b2596b5SMatthias Ringwald mckr = (mckr & (~PMC_MCKR_CSS_Msk)) | PMC_MCKR_CSS_MAIN_CLK;
120*1b2596b5SMatthias Ringwald PMC->PMC_MCKR = mckr;
121*1b2596b5SMatthias Ringwald while(!(PMC->PMC_SR & PMC_SR_MCKRDY));
122*1b2596b5SMatthias Ringwald }
123*1b2596b5SMatthias Ringwald /* MCK prescale -> 1 */
124*1b2596b5SMatthias Ringwald if (mckr & PMC_MCKR_PRES_Msk) {
125*1b2596b5SMatthias Ringwald mckr = (mckr & (~PMC_MCKR_PRES_Msk));
126*1b2596b5SMatthias Ringwald PMC->PMC_MCKR = mckr;
127*1b2596b5SMatthias Ringwald while(!(PMC->PMC_SR & PMC_SR_MCKRDY));
128*1b2596b5SMatthias Ringwald }
129*1b2596b5SMatthias Ringwald /* Disable PLLs */
130*1b2596b5SMatthias Ringwald pmc_disable_pllack();
131*1b2596b5SMatthias Ringwald #if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)
132*1b2596b5SMatthias Ringwald pmc_disable_pllbck();
133*1b2596b5SMatthias Ringwald #elif (SAM3U || SAM3XA)
134*1b2596b5SMatthias Ringwald pmc_disable_upll_clock();
135*1b2596b5SMatthias Ringwald #endif
136*1b2596b5SMatthias Ringwald
137*1b2596b5SMatthias Ringwald /* Prepare for entering WAIT mode */
138*1b2596b5SMatthias Ringwald /* Wait fast RC ready */
139*1b2596b5SMatthias Ringwald while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));
140*1b2596b5SMatthias Ringwald
141*1b2596b5SMatthias Ringwald /* Switch mainck to FAST RC */
142*1b2596b5SMatthias Ringwald #if SAMG
143*1b2596b5SMatthias Ringwald /**
144*1b2596b5SMatthias Ringwald * For the sleepwalking feature, we need an accurate RC clock. Only 24M and
145*1b2596b5SMatthias Ringwald * 16M are trimmed in production. Here we select the 24M.
146*1b2596b5SMatthias Ringwald * And so wait state need to be 1.
147*1b2596b5SMatthias Ringwald */
148*1b2596b5SMatthias Ringwald EFC0->EEFC_FMR = (fmr & (~EEFC_FMR_FWS_Msk)) | EEFC_FMR_FWS(1);
149*1b2596b5SMatthias Ringwald
150*1b2596b5SMatthias Ringwald PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) | CKGR_MOR_MOSCRCF_24_MHz |
151*1b2596b5SMatthias Ringwald CKGR_MOR_KEY_PASSWD;
152*1b2596b5SMatthias Ringwald #else
153*1b2596b5SMatthias Ringwald PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) |
154*1b2596b5SMatthias Ringwald CKGR_MOR_KEY_PASSWD;
155*1b2596b5SMatthias Ringwald #endif
156*1b2596b5SMatthias Ringwald while (!(PMC->PMC_SR & PMC_SR_MOSCSELS));
157*1b2596b5SMatthias Ringwald
158*1b2596b5SMatthias Ringwald #if (!SAMG)
159*1b2596b5SMatthias Ringwald /* FWS update */
160*1b2596b5SMatthias Ringwald EFC0->EEFC_FMR = fmr & (~EEFC_FMR_FWS_Msk);
161*1b2596b5SMatthias Ringwald #if defined(EFC1)
162*1b2596b5SMatthias Ringwald EFC1->EEFC_FMR = fmr1 & (~EEFC_FMR_FWS_Msk);
163*1b2596b5SMatthias Ringwald #endif
164*1b2596b5SMatthias Ringwald #endif
165*1b2596b5SMatthias Ringwald
166*1b2596b5SMatthias Ringwald /* Disable XTALs */
167*1b2596b5SMatthias Ringwald if (disable_xtal) {
168*1b2596b5SMatthias Ringwald PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |
169*1b2596b5SMatthias Ringwald CKGR_MOR_KEY_PASSWD;
170*1b2596b5SMatthias Ringwald }
171*1b2596b5SMatthias Ringwald }
172*1b2596b5SMatthias Ringwald
173*1b2596b5SMatthias Ringwald /**
174*1b2596b5SMatthias Ringwald * Restore clock settings
175*1b2596b5SMatthias Ringwald */
pmc_restore_clock_setting(const uint32_t osc_setting,const uint32_t pll0_setting,const uint32_t pll1_setting,const uint32_t mck_setting,const uint32_t fmr_setting,const uint32_t fmr_setting1)176*1b2596b5SMatthias Ringwald __always_inline static void pmc_restore_clock_setting(
177*1b2596b5SMatthias Ringwald const uint32_t osc_setting,
178*1b2596b5SMatthias Ringwald const uint32_t pll0_setting,
179*1b2596b5SMatthias Ringwald const uint32_t pll1_setting,
180*1b2596b5SMatthias Ringwald const uint32_t mck_setting,
181*1b2596b5SMatthias Ringwald const uint32_t fmr_setting
182*1b2596b5SMatthias Ringwald #if defined(EFC1)
183*1b2596b5SMatthias Ringwald , const uint32_t fmr_setting1
184*1b2596b5SMatthias Ringwald #endif
185*1b2596b5SMatthias Ringwald )
186*1b2596b5SMatthias Ringwald {
187*1b2596b5SMatthias Ringwald uint32_t mckr;
188*1b2596b5SMatthias Ringwald uint32_t pll_sr = 0;
189*1b2596b5SMatthias Ringwald
190*1b2596b5SMatthias Ringwald /* Switch mainck to external xtal */
191*1b2596b5SMatthias Ringwald if (CKGR_MOR_MOSCXTBY == (osc_setting & CKGR_MOR_MOSCXTBY)) {
192*1b2596b5SMatthias Ringwald /* Bypass mode */
193*1b2596b5SMatthias Ringwald PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |
194*1b2596b5SMatthias Ringwald CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTBY |
195*1b2596b5SMatthias Ringwald CKGR_MOR_MOSCSEL;
196*1b2596b5SMatthias Ringwald PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCEN &
197*1b2596b5SMatthias Ringwald ~CKGR_MOR_MOSCRCF_Msk)
198*1b2596b5SMatthias Ringwald | CKGR_MOR_KEY_PASSWD;
199*1b2596b5SMatthias Ringwald } else if (CKGR_MOR_MOSCXTEN == (osc_setting & CKGR_MOR_MOSCXTEN)) {
200*1b2596b5SMatthias Ringwald /* Enable External XTAL */
201*1b2596b5SMatthias Ringwald if (!(PMC->CKGR_MOR & CKGR_MOR_MOSCXTEN)) {
202*1b2596b5SMatthias Ringwald PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) |
203*1b2596b5SMatthias Ringwald CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTEN;
204*1b2596b5SMatthias Ringwald /* Wait the Xtal to stabilize */
205*1b2596b5SMatthias Ringwald while (!(PMC->PMC_SR & PMC_SR_MOSCXTS));
206*1b2596b5SMatthias Ringwald }
207*1b2596b5SMatthias Ringwald /* Select External XTAL */
208*1b2596b5SMatthias Ringwald if (!(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)) {
209*1b2596b5SMatthias Ringwald PMC->CKGR_MOR |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCSEL;
210*1b2596b5SMatthias Ringwald while (!(PMC->PMC_SR & PMC_SR_MOSCSELS));
211*1b2596b5SMatthias Ringwald }
212*1b2596b5SMatthias Ringwald /* Disable Fast RC */
213*1b2596b5SMatthias Ringwald PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCEN &
214*1b2596b5SMatthias Ringwald ~CKGR_MOR_MOSCRCF_Msk)
215*1b2596b5SMatthias Ringwald | CKGR_MOR_KEY_PASSWD;
216*1b2596b5SMatthias Ringwald }
217*1b2596b5SMatthias Ringwald
218*1b2596b5SMatthias Ringwald if (pll0_setting & CKGR_PLLAR_MULA_Msk) {
219*1b2596b5SMatthias Ringwald #if (SAM4C || SAM4CM || SAMG || SAM4CP)
220*1b2596b5SMatthias Ringwald PMC->CKGR_PLLAR = pll0_setting;
221*1b2596b5SMatthias Ringwald #else
222*1b2596b5SMatthias Ringwald PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | pll0_setting;
223*1b2596b5SMatthias Ringwald #endif
224*1b2596b5SMatthias Ringwald pll_sr |= PMC_SR_LOCKA;
225*1b2596b5SMatthias Ringwald }
226*1b2596b5SMatthias Ringwald #if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)
227*1b2596b5SMatthias Ringwald if (pll1_setting & CKGR_PLLBR_MULB_Msk) {
228*1b2596b5SMatthias Ringwald PMC->CKGR_PLLBR = pll1_setting;
229*1b2596b5SMatthias Ringwald pll_sr |= PMC_SR_LOCKB;
230*1b2596b5SMatthias Ringwald }
231*1b2596b5SMatthias Ringwald #elif (SAM3U || SAM3XA)
232*1b2596b5SMatthias Ringwald if (pll1_setting & CKGR_UCKR_UPLLEN) {
233*1b2596b5SMatthias Ringwald PMC->CKGR_UCKR = pll1_setting;
234*1b2596b5SMatthias Ringwald pll_sr |= PMC_SR_LOCKU;
235*1b2596b5SMatthias Ringwald }
236*1b2596b5SMatthias Ringwald #else
237*1b2596b5SMatthias Ringwald UNUSED(pll1_setting);
238*1b2596b5SMatthias Ringwald #endif
239*1b2596b5SMatthias Ringwald /* Wait MCK source ready */
240*1b2596b5SMatthias Ringwald switch(mck_setting & PMC_MCKR_CSS_Msk) {
241*1b2596b5SMatthias Ringwald case PMC_MCKR_CSS_PLLA_CLK:
242*1b2596b5SMatthias Ringwald while (!(PMC->PMC_SR & PMC_SR_LOCKA));
243*1b2596b5SMatthias Ringwald break;
244*1b2596b5SMatthias Ringwald #if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)
245*1b2596b5SMatthias Ringwald case PMC_MCKR_CSS_PLLB_CLK:
246*1b2596b5SMatthias Ringwald while (!(PMC->PMC_SR & PMC_SR_LOCKB));
247*1b2596b5SMatthias Ringwald break;
248*1b2596b5SMatthias Ringwald #elif (SAM3U || SAM3XA)
249*1b2596b5SMatthias Ringwald case PMC_MCKR_CSS_UPLL_CLK:
250*1b2596b5SMatthias Ringwald while (!(PMC->PMC_SR & PMC_SR_LOCKU));
251*1b2596b5SMatthias Ringwald break;
252*1b2596b5SMatthias Ringwald #endif
253*1b2596b5SMatthias Ringwald }
254*1b2596b5SMatthias Ringwald
255*1b2596b5SMatthias Ringwald /* Switch to faster clock */
256*1b2596b5SMatthias Ringwald mckr = PMC->PMC_MCKR;
257*1b2596b5SMatthias Ringwald
258*1b2596b5SMatthias Ringwald /* Set PRES */
259*1b2596b5SMatthias Ringwald PMC->PMC_MCKR = (mckr & ~PMC_MCKR_PRES_Msk)
260*1b2596b5SMatthias Ringwald | (mck_setting & PMC_MCKR_PRES_Msk);
261*1b2596b5SMatthias Ringwald while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
262*1b2596b5SMatthias Ringwald
263*1b2596b5SMatthias Ringwald /* Restore flash wait states */
264*1b2596b5SMatthias Ringwald EFC0->EEFC_FMR = fmr_setting;
265*1b2596b5SMatthias Ringwald #if defined(EFC1)
266*1b2596b5SMatthias Ringwald EFC1->EEFC_FMR = fmr_setting1;
267*1b2596b5SMatthias Ringwald #endif
268*1b2596b5SMatthias Ringwald
269*1b2596b5SMatthias Ringwald /* Set CSS and others */
270*1b2596b5SMatthias Ringwald PMC->PMC_MCKR = mck_setting;
271*1b2596b5SMatthias Ringwald while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
272*1b2596b5SMatthias Ringwald
273*1b2596b5SMatthias Ringwald /* Waiting all restored PLLs ready */
274*1b2596b5SMatthias Ringwald while (!(PMC->PMC_SR & pll_sr));
275*1b2596b5SMatthias Ringwald }
276*1b2596b5SMatthias Ringwald
277*1b2596b5SMatthias Ringwald /** If clocks are switched for some sleep mode */
278*1b2596b5SMatthias Ringwald static volatile bool b_is_sleep_clock_used = false;
279*1b2596b5SMatthias Ringwald /** Callback invoked once when clocks are restored */
280*1b2596b5SMatthias Ringwald static pmc_callback_wakeup_clocks_restored_t callback_clocks_restored = NULL;
281*1b2596b5SMatthias Ringwald
pmc_sleep(int sleep_mode)282*1b2596b5SMatthias Ringwald void pmc_sleep(int sleep_mode)
283*1b2596b5SMatthias Ringwald {
284*1b2596b5SMatthias Ringwald switch (sleep_mode) {
285*1b2596b5SMatthias Ringwald #if (!(SAMG51 || SAMG53 || SAMG54))
286*1b2596b5SMatthias Ringwald case SAM_PM_SMODE_SLEEP_WFI:
287*1b2596b5SMatthias Ringwald case SAM_PM_SMODE_SLEEP_WFE:
288*1b2596b5SMatthias Ringwald #if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAM4CP || SAMG55 || SAMV71 || SAMV70 || SAMS70 || SAME70)
289*1b2596b5SMatthias Ringwald SCB->SCR &= (uint32_t)~SCR_SLEEPDEEP;
290*1b2596b5SMatthias Ringwald cpu_irq_enable();
291*1b2596b5SMatthias Ringwald __WFI();
292*1b2596b5SMatthias Ringwald break;
293*1b2596b5SMatthias Ringwald #else
294*1b2596b5SMatthias Ringwald PMC->PMC_FSMR &= (uint32_t)~PMC_FSMR_LPM;
295*1b2596b5SMatthias Ringwald SCB->SCR &= (uint32_t)~SCR_SLEEPDEEP;
296*1b2596b5SMatthias Ringwald cpu_irq_enable();
297*1b2596b5SMatthias Ringwald if (sleep_mode == SAM_PM_SMODE_SLEEP_WFI)
298*1b2596b5SMatthias Ringwald __WFI();
299*1b2596b5SMatthias Ringwald else
300*1b2596b5SMatthias Ringwald __WFE();
301*1b2596b5SMatthias Ringwald break;
302*1b2596b5SMatthias Ringwald #endif
303*1b2596b5SMatthias Ringwald #endif
304*1b2596b5SMatthias Ringwald
305*1b2596b5SMatthias Ringwald case SAM_PM_SMODE_WAIT_FAST:
306*1b2596b5SMatthias Ringwald case SAM_PM_SMODE_WAIT: {
307*1b2596b5SMatthias Ringwald uint32_t mor, pllr0, pllr1, mckr;
308*1b2596b5SMatthias Ringwald uint32_t fmr;
309*1b2596b5SMatthias Ringwald #if defined(EFC1)
310*1b2596b5SMatthias Ringwald uint32_t fmr1;
311*1b2596b5SMatthias Ringwald #endif
312*1b2596b5SMatthias Ringwald #if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAM4CP || SAMG55 || SAMV71 || SAMV70 || SAMS70 || SAME70)
313*1b2596b5SMatthias Ringwald (sleep_mode == SAM_PM_SMODE_WAIT_FAST) ?
314*1b2596b5SMatthias Ringwald pmc_set_flash_in_wait_mode(PMC_FSMR_FLPM_FLASH_STANDBY) :
315*1b2596b5SMatthias Ringwald pmc_set_flash_in_wait_mode(PMC_FSMR_FLPM_FLASH_DEEP_POWERDOWN);
316*1b2596b5SMatthias Ringwald #endif
317*1b2596b5SMatthias Ringwald cpu_irq_disable();
318*1b2596b5SMatthias Ringwald b_is_sleep_clock_used = true;
319*1b2596b5SMatthias Ringwald
320*1b2596b5SMatthias Ringwald #if (SAM4C || SAM4CM || SAM4CP)
321*1b2596b5SMatthias Ringwald /* Backup the sub-system 1 status and stop sub-system 1 */
322*1b2596b5SMatthias Ringwald uint32_t cpclk_backup = PMC->PMC_SCSR &
323*1b2596b5SMatthias Ringwald (PMC_SCSR_CPCK | PMC_SCSR_CPBMCK);
324*1b2596b5SMatthias Ringwald PMC->PMC_SCDR = cpclk_backup | PMC_SCDR_CPKEY_PASSWD;
325*1b2596b5SMatthias Ringwald #endif
326*1b2596b5SMatthias Ringwald pmc_save_clock_settings(&mor, &pllr0, &pllr1, &mckr, &fmr,
327*1b2596b5SMatthias Ringwald #if defined(EFC1)
328*1b2596b5SMatthias Ringwald &fmr1,
329*1b2596b5SMatthias Ringwald #endif
330*1b2596b5SMatthias Ringwald (sleep_mode == SAM_PM_SMODE_WAIT));
331*1b2596b5SMatthias Ringwald
332*1b2596b5SMatthias Ringwald /* Enter wait mode */
333*1b2596b5SMatthias Ringwald cpu_irq_enable();
334*1b2596b5SMatthias Ringwald
335*1b2596b5SMatthias Ringwald pmc_enable_waitmode();
336*1b2596b5SMatthias Ringwald
337*1b2596b5SMatthias Ringwald cpu_irq_disable();
338*1b2596b5SMatthias Ringwald pmc_restore_clock_setting(mor, pllr0, pllr1, mckr, fmr
339*1b2596b5SMatthias Ringwald #if defined(EFC1)
340*1b2596b5SMatthias Ringwald , fmr1
341*1b2596b5SMatthias Ringwald #endif
342*1b2596b5SMatthias Ringwald );
343*1b2596b5SMatthias Ringwald
344*1b2596b5SMatthias Ringwald #if (SAM4C || SAM4CM || SAM4CP)
345*1b2596b5SMatthias Ringwald /* Restore the sub-system 1 */
346*1b2596b5SMatthias Ringwald PMC->PMC_SCER = cpclk_backup | PMC_SCER_CPKEY_PASSWD;
347*1b2596b5SMatthias Ringwald #endif
348*1b2596b5SMatthias Ringwald b_is_sleep_clock_used = false;
349*1b2596b5SMatthias Ringwald if (callback_clocks_restored) {
350*1b2596b5SMatthias Ringwald callback_clocks_restored();
351*1b2596b5SMatthias Ringwald callback_clocks_restored = NULL;
352*1b2596b5SMatthias Ringwald }
353*1b2596b5SMatthias Ringwald cpu_irq_enable();
354*1b2596b5SMatthias Ringwald
355*1b2596b5SMatthias Ringwald break;
356*1b2596b5SMatthias Ringwald }
357*1b2596b5SMatthias Ringwald #if (!(SAMG51 || SAMG53 || SAMG54))
358*1b2596b5SMatthias Ringwald case SAM_PM_SMODE_BACKUP:
359*1b2596b5SMatthias Ringwald SCB->SCR |= SCR_SLEEPDEEP;
360*1b2596b5SMatthias Ringwald #if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAM4CP || SAMG55 || SAMV71 || SAMV70 || SAMS70 || SAME70)
361*1b2596b5SMatthias Ringwald SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_VROFF_STOP_VREG;
362*1b2596b5SMatthias Ringwald cpu_irq_enable();
363*1b2596b5SMatthias Ringwald __WFI() ;
364*1b2596b5SMatthias Ringwald #else
365*1b2596b5SMatthias Ringwald cpu_irq_enable();
366*1b2596b5SMatthias Ringwald __WFE() ;
367*1b2596b5SMatthias Ringwald #endif
368*1b2596b5SMatthias Ringwald break;
369*1b2596b5SMatthias Ringwald #endif
370*1b2596b5SMatthias Ringwald }
371*1b2596b5SMatthias Ringwald }
372*1b2596b5SMatthias Ringwald
pmc_is_wakeup_clocks_restored(void)373*1b2596b5SMatthias Ringwald bool pmc_is_wakeup_clocks_restored(void)
374*1b2596b5SMatthias Ringwald {
375*1b2596b5SMatthias Ringwald return !b_is_sleep_clock_used;
376*1b2596b5SMatthias Ringwald }
377*1b2596b5SMatthias Ringwald
pmc_wait_wakeup_clocks_restore(pmc_callback_wakeup_clocks_restored_t callback)378*1b2596b5SMatthias Ringwald void pmc_wait_wakeup_clocks_restore(
379*1b2596b5SMatthias Ringwald pmc_callback_wakeup_clocks_restored_t callback)
380*1b2596b5SMatthias Ringwald {
381*1b2596b5SMatthias Ringwald if (b_is_sleep_clock_used) {
382*1b2596b5SMatthias Ringwald cpu_irq_disable();
383*1b2596b5SMatthias Ringwald callback_clocks_restored = callback;
384*1b2596b5SMatthias Ringwald } else if (callback) {
385*1b2596b5SMatthias Ringwald callback();
386*1b2596b5SMatthias Ringwald }
387*1b2596b5SMatthias Ringwald }
388*1b2596b5SMatthias Ringwald
389*1b2596b5SMatthias Ringwald #endif
390