1 /******************************************************************************
2 *  Filename:       prcm.c
3 *
4 *  Description:    Driver for the PRCM.
5 *
6 *  Copyright (c) 2015 - 2022, Texas Instruments Incorporated
7 *  All rights reserved.
8 *
9 *  Redistribution and use in source and binary forms, with or without
10 *  modification, are permitted provided that the following conditions are met:
11 *
12 *  1) Redistributions of source code must retain the above copyright notice,
13 *     this list of conditions and the following disclaimer.
14 *
15 *  2) Redistributions in binary form must reproduce the above copyright notice,
16 *     this list of conditions and the following disclaimer in the documentation
17 *     and/or other materials provided with the distribution.
18 *
19 *  3) Neither the name of the ORGANIZATION nor the names of its contributors may
20 *     be used to endorse or promote products derived from this software without
21 *     specific prior written permission.
22 *
23 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 *  POSSIBILITY OF SUCH DAMAGE.
34 *
35 ******************************************************************************/
36 
37 #include "prcm.h"
38 
39 //*****************************************************************************
40 //
41 // Handle support for DriverLib in ROM:
42 // This section will undo prototype renaming made in the header file
43 //
44 //*****************************************************************************
45 #if !defined(DOXYGEN)
46     #undef  PRCMInfClockConfigureSet
47     #define PRCMInfClockConfigureSet        NOROM_PRCMInfClockConfigureSet
48     #undef  PRCMInfClockConfigureGet
49     #define PRCMInfClockConfigureGet        NOROM_PRCMInfClockConfigureGet
50     #undef  PRCMAudioClockConfigSet
51     #define PRCMAudioClockConfigSet         NOROM_PRCMAudioClockConfigSet
52     #undef  PRCMAudioClockConfigSetOverride
53     #define PRCMAudioClockConfigSetOverride NOROM_PRCMAudioClockConfigSetOverride
54     #undef  PRCMAudioClockInternalSource
55     #define PRCMAudioClockInternalSource    NOROM_PRCMAudioClockInternalSource
56     #undef  PRCMAudioClockExternalSource
57     #define PRCMAudioClockExternalSource    NOROM_PRCMAudioClockExternalSource
58     #undef  PRCMPowerDomainOn
59     #define PRCMPowerDomainOn               NOROM_PRCMPowerDomainOn
60     #undef  PRCMPowerDomainOff
61     #define PRCMPowerDomainOff              NOROM_PRCMPowerDomainOff
62     #undef  PRCMPeripheralRunEnable
63     #define PRCMPeripheralRunEnable         NOROM_PRCMPeripheralRunEnable
64     #undef  PRCMPeripheralRunDisable
65     #define PRCMPeripheralRunDisable        NOROM_PRCMPeripheralRunDisable
66     #undef  PRCMPeripheralSleepEnable
67     #define PRCMPeripheralSleepEnable       NOROM_PRCMPeripheralSleepEnable
68     #undef  PRCMPeripheralSleepDisable
69     #define PRCMPeripheralSleepDisable      NOROM_PRCMPeripheralSleepDisable
70     #undef  PRCMPeripheralDeepSleepEnable
71     #define PRCMPeripheralDeepSleepEnable   NOROM_PRCMPeripheralDeepSleepEnable
72     #undef  PRCMPeripheralDeepSleepDisable
73     #define PRCMPeripheralDeepSleepDisable  NOROM_PRCMPeripheralDeepSleepDisable
74     #undef  PRCMPowerDomainsAllOff
75     #define PRCMPowerDomainsAllOff          NOROM_PRCMPowerDomainsAllOff
76     #undef  PRCMPowerDomainsAllOn
77     #define PRCMPowerDomainsAllOn           NOROM_PRCMPowerDomainsAllOn
78     #undef  PRCMDeepSleep
79     #define PRCMDeepSleep                   NOROM_PRCMDeepSleep
80 #endif
81 
82 
83 //*****************************************************************************
84 //
85 // Arrays that maps the "peripheral set" number (which is stored in
86 // bits[11:8] of the PRCM_PERIPH_* defines) to the PRCM register that
87 // contains the relevant bit for that peripheral.
88 //
89 //*****************************************************************************
90 
91 // Run mode registers
92 static const uint32_t g_pui32RCGCRegs[] =
93 {
94     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_GPTCLKGR),  // Index 0
95     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_SSICLKGR),  // Index 1
96     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_UARTCLKGR), // Index 2
97     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2CCLKGR),  // Index 3
98     (PRCM_BASE + PRCM_O_SECDMACLKGR),                  // Index 4
99     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_GPIOCLKGR), // Index 5
100     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SCLKGR)   // Index 6
101 };
102 
103 // Sleep mode registers
104 static const uint32_t g_pui32SCGCRegs[] =
105 {
106     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_GPTCLKGS),  // Index 0
107     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_SSICLKGS),  // Index 1
108     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_UARTCLKGS), // Index 2
109     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2CCLKGS),  // Index 3
110     (PRCM_BASE + PRCM_O_SECDMACLKGS),                  // Index 4
111     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_GPIOCLKGS), // Index 5
112     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SCLKGS)   // Index 6
113 };
114 
115 // Deep sleep mode registers
116 static const uint32_t g_pui32DCGCRegs[] =
117 {
118     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_GPTCLKGDS),  // Index 0
119     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_SSICLKGDS),  // Index 1
120     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_UARTCLKGDS), // Index 2
121     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2CCLKGDS),  // Index 3
122     (PRCM_BASE + PRCM_O_SECDMACLKGDS),                  // Index 4
123     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_GPIOCLKGDS), // Index 5
124     (PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SCLKGDS)   // Index 6
125 };
126 
127 //*****************************************************************************
128 //
129 // This macro extracts the array index out of the peripheral number
130 //
131 //*****************************************************************************
132 #define PRCM_PERIPH_INDEX(a)  (((a) >> 8) & 0xf)
133 
134 //*****************************************************************************
135 //
136 // This macro extracts the peripheral instance number and generates bit mask
137 //
138 //*****************************************************************************
139 #define PRCM_PERIPH_MASKBIT(a) (0x00000001 << ((a) & 0x1f))
140 
141 
142 //*****************************************************************************
143 //
144 // Configure the infrastructure clock.
145 //
146 //*****************************************************************************
147 void
PRCMInfClockConfigureSet(uint32_t ui32ClkDiv,uint32_t ui32PowerMode)148 PRCMInfClockConfigureSet(uint32_t ui32ClkDiv, uint32_t ui32PowerMode)
149 {
150     uint32_t ui32Divisor;
151 
152     // Check the arguments.
153     ASSERT((ui32ClkDiv == PRCM_CLOCK_DIV_1) ||
154            (ui32ClkDiv == PRCM_CLOCK_DIV_2) ||
155            (ui32ClkDiv == PRCM_CLOCK_DIV_8) ||
156            (ui32ClkDiv == PRCM_CLOCK_DIV_32));
157     ASSERT((ui32PowerMode == PRCM_RUN_MODE) ||
158            (ui32PowerMode == PRCM_SLEEP_MODE) ||
159            (ui32PowerMode == PRCM_DEEP_SLEEP_MODE));
160 
161     ui32Divisor = 0;
162 
163     // Find the correct division factor.
164     if(ui32ClkDiv == PRCM_CLOCK_DIV_1)
165     {
166         ui32Divisor = 0x0;
167     }
168     else if(ui32ClkDiv == PRCM_CLOCK_DIV_2)
169     {
170         ui32Divisor = 0x1;
171     }
172     else if(ui32ClkDiv == PRCM_CLOCK_DIV_8)
173     {
174         ui32Divisor = 0x2;
175     }
176     else if(ui32ClkDiv == PRCM_CLOCK_DIV_32)
177     {
178         ui32Divisor = 0x3;
179     }
180 
181     // Determine the correct power mode set the division factor accordingly.
182     if(ui32PowerMode == PRCM_RUN_MODE)
183     {
184         HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_INFRCLKDIVR) = ui32Divisor;
185     }
186     else if(ui32PowerMode == PRCM_SLEEP_MODE)
187     {
188         HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_INFRCLKDIVS) = ui32Divisor;
189     }
190     else if(ui32PowerMode == PRCM_DEEP_SLEEP_MODE)
191     {
192         HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_INFRCLKDIVDS) = ui32Divisor;
193     }
194 }
195 
196 //*****************************************************************************
197 //
198 // Use this function to get the infrastructure clock configuration
199 //
200 //*****************************************************************************
201 uint32_t
PRCMInfClockConfigureGet(uint32_t ui32PowerMode)202 PRCMInfClockConfigureGet(uint32_t ui32PowerMode)
203 {
204     uint32_t ui32ClkDiv;
205     uint32_t ui32Divisor;
206 
207     // Check the arguments.
208     ASSERT((ui32PowerMode == PRCM_RUN_MODE) ||
209            (ui32PowerMode == PRCM_SLEEP_MODE) ||
210            (ui32PowerMode == PRCM_DEEP_SLEEP_MODE));
211 
212     ui32ClkDiv = 0;
213     ui32Divisor = 0;
214 
215     // Determine the correct power mode.
216     if(ui32PowerMode == PRCM_RUN_MODE)
217     {
218         ui32ClkDiv = HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_INFRCLKDIVR);
219     }
220     else if(ui32PowerMode == PRCM_SLEEP_MODE)
221     {
222         ui32ClkDiv = HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_INFRCLKDIVS);
223     }
224     else if(ui32PowerMode == PRCM_DEEP_SLEEP_MODE)
225     {
226         ui32ClkDiv = HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_INFRCLKDIVDS);
227     }
228 
229     // Find the correct division factor.
230     if(ui32ClkDiv == 0x0)
231     {
232         ui32Divisor = PRCM_CLOCK_DIV_1;
233     }
234     else if(ui32ClkDiv == 0x1)
235     {
236         ui32Divisor = PRCM_CLOCK_DIV_2;
237     }
238     else if(ui32ClkDiv == 0x2)
239     {
240         ui32Divisor = PRCM_CLOCK_DIV_8;
241     }
242     else if(ui32ClkDiv == 0x3)
243     {
244         ui32Divisor = PRCM_CLOCK_DIV_32;
245     }
246 
247     // Return the clock division factor.
248     return ui32Divisor;
249 }
250 
251 
252 //*****************************************************************************
253 //
254 // Configure the audio clock generation
255 //
256 //*****************************************************************************
257 void
PRCMAudioClockConfigSet(uint32_t ui32ClkConfig,uint32_t ui32SampleRate)258 PRCMAudioClockConfigSet(uint32_t ui32ClkConfig, uint32_t ui32SampleRate)
259 {
260     uint32_t ui32Reg;
261     uint32_t ui32MstDiv;
262     uint32_t ui32BitDiv;
263     uint32_t ui32WordDiv;
264 
265     // Check the arguments.
266     ASSERT(!(ui32ClkConfig & (PRCM_I2SCLKCTL_WCLK_PHASE_M | PRCM_I2SCLKCTL_SMPL_ON_POSEDGE_M)));
267     ASSERT((ui32SampleRate == I2S_SAMPLE_RATE_16K) ||
268            (ui32SampleRate == I2S_SAMPLE_RATE_24K) ||
269            (ui32SampleRate == I2S_SAMPLE_RATE_32K) ||
270            (ui32SampleRate == I2S_SAMPLE_RATE_48K));
271 
272     ui32MstDiv = 0;
273     ui32BitDiv = 0;
274     ui32WordDiv = 0;
275 
276     // Make sure the audio clock generation is disabled before reconfiguring.
277     PRCMAudioClockDisable();
278 
279     // Define the clock division factors for the audio interface.
280     switch(ui32SampleRate)
281     {
282     case I2S_SAMPLE_RATE_16K :
283         ui32MstDiv = 6;
284         ui32BitDiv = 60;
285         ui32WordDiv = 25;
286         break;
287     case I2S_SAMPLE_RATE_24K :
288         ui32MstDiv = 4;
289         ui32BitDiv = 40;
290         ui32WordDiv = 25;
291         break;
292     case I2S_SAMPLE_RATE_32K :
293         ui32MstDiv = 3;
294         ui32BitDiv = 30;
295         ui32WordDiv = 25;
296         break;
297     case I2S_SAMPLE_RATE_48K :
298         ui32MstDiv = 2;
299         ui32BitDiv = 20;
300         ui32WordDiv = 25;
301         break;
302     }
303 
304     // Make sure to compensate the Frame clock division factor if using single
305     // phase format.
306     if((ui32ClkConfig & PRCM_I2SCLKCTL_WCLK_PHASE_M) == PRCM_WCLK_SINGLE_PHASE)
307     {
308         ui32WordDiv -= 1;
309     }
310 
311     // Write the clock division factors.
312     HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SMCLKDIV) = ui32MstDiv;
313     HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SBCLKDIV) = ui32BitDiv;
314     HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SWCLKDIV) = ui32WordDiv;
315 
316     // Configure the Word clock format and polarity.
317     ui32Reg = HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SCLKCTL) & ~(PRCM_I2SCLKCTL_WCLK_PHASE_M |
318               PRCM_I2SCLKCTL_SMPL_ON_POSEDGE_M);
319     HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SCLKCTL) = ui32Reg | ui32ClkConfig;
320 }
321 
322 //*****************************************************************************
323 //
324 // Configure the audio clock generation with manual setting of clock divider.
325 //
326 //*****************************************************************************
327 void
PRCMAudioClockConfigSetOverride(uint32_t ui32ClkConfig,uint32_t ui32MstDiv,uint32_t ui32BitDiv,uint32_t ui32WordDiv)328 PRCMAudioClockConfigSetOverride(uint32_t ui32ClkConfig, uint32_t ui32MstDiv,
329                         uint32_t ui32BitDiv, uint32_t ui32WordDiv)
330 {
331     uint32_t ui32Reg;
332 
333     // Check the arguments.
334     ASSERT(!(ui32ClkConfig & (PRCM_I2SCLKCTL_WCLK_PHASE_M | PRCM_I2SCLKCTL_SMPL_ON_POSEDGE_M)));
335 
336     // Make sure the audio clock generation is disabled before reconfiguring.
337     PRCMAudioClockDisable();
338 
339     // Make sure to compensate the Frame clock division factor if using single
340     // phase format.
341     if((ui32ClkConfig & PRCM_I2SCLKCTL_WCLK_PHASE_M) == PRCM_WCLK_SINGLE_PHASE)
342     {
343         ui32WordDiv -= 1;
344     }
345 
346     // Write the clock division factors.
347     HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SMCLKDIV) = ui32MstDiv;
348     HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SBCLKDIV) = ui32BitDiv;
349     HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SWCLKDIV) = ui32WordDiv;
350 
351     // Configure the Word clock format and polarity.
352     ui32Reg = HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SCLKCTL) & ~(PRCM_I2SCLKCTL_WCLK_PHASE_M |
353               PRCM_I2SCLKCTL_SMPL_ON_POSEDGE_M);
354     HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SCLKCTL) = ui32Reg | ui32ClkConfig;
355 }
356 
357 //*****************************************************************************
358 //
359 // Configure the audio clocks for I2S module
360 //
361 //*****************************************************************************
362 void
PRCMAudioClockConfigOverride(uint8_t ui8SamplingEdge,uint8_t ui8WCLKPhase,uint32_t ui32MstDiv,uint32_t ui32BitDiv,uint32_t ui32WordDiv)363 PRCMAudioClockConfigOverride(uint8_t  ui8SamplingEdge,
364                              uint8_t  ui8WCLKPhase,
365                              uint32_t ui32MstDiv,
366                              uint32_t ui32BitDiv,
367                              uint32_t ui32WordDiv)
368 {
369     // Check the arguments.
370     ASSERT(ui8SamplingEdge == PRCM_I2S_WCLK_NEG_EDGE ||
371            ui8SamplingEdge == PRCM_I2S_WCLK_POS_EDGE);
372     ASSERT(ui8WCLKPhase == PRCM_WCLK_SINGLE_PHASE ||
373            ui8WCLKPhase == PRCM_WCLK_DUAL_PHASE   ||
374            ui8WCLKPhase == PRCM_WCLK_USER_DEF);
375 
376     // Make sure the audio clock generation is disabled before reconfiguring.
377     PRCMAudioClockDisable();
378 
379     // Make sure to compensate the Frame clock division factor if using single
380     // phase format.
381     if((ui8WCLKPhase) == PRCM_WCLK_SINGLE_PHASE)
382     {
383         ui32WordDiv -= 1;
384     }
385 
386     // Write the clock division factors.
387     HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SMCLKDIV) = ui32MstDiv;
388     HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SBCLKDIV) = ui32BitDiv;
389     HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SWCLKDIV) = ui32WordDiv;
390 
391     // Configure the Word clock format and polarity and enable it.
392     HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SCLKCTL) =  (ui8SamplingEdge  << PRCM_I2SCLKCTL_SMPL_ON_POSEDGE_S) |
393                                            (ui8WCLKPhase     << PRCM_I2SCLKCTL_WCLK_PHASE_S     ) |
394                                            (1                << PRCM_I2SCLKCTL_EN_S             );
395 }
396 
397 //*****************************************************************************
398 //
399 // Configure the clocks as "internally generated".
400 //
401 //*****************************************************************************
PRCMAudioClockInternalSource(void)402 void PRCMAudioClockInternalSource(void)
403 {
404     HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SBCLKSEL) = PRCM_I2SBCLKSEL_SRC;
405 }
406 
407 //*****************************************************************************
408 //
409 // Configure the clocks as "externally generated".
410 //
411 //*****************************************************************************
PRCMAudioClockExternalSource(void)412 void PRCMAudioClockExternalSource(void)
413 {
414     HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_I2SBCLKSEL) = 0;
415 }
416 
417 //*****************************************************************************
418 //
419 // Turn power on in power domains in the MCU domain
420 //
421 //*****************************************************************************
422 void
PRCMPowerDomainOn(uint32_t ui32Domains)423 PRCMPowerDomainOn(uint32_t ui32Domains)
424 {
425     // Check the arguments.
426     ASSERT((ui32Domains & PRCM_DOMAIN_RFCORE) ||
427            (ui32Domains & PRCM_DOMAIN_SERIAL) ||
428            (ui32Domains & PRCM_DOMAIN_PERIPH) ||
429            (ui32Domains & PRCM_DOMAIN_CPU) ||
430            (ui32Domains & PRCM_DOMAIN_VIMS));
431 
432     // Assert the request to power on the right domains.
433     if(ui32Domains & PRCM_DOMAIN_RFCORE)
434     {
435         HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_PDCTL0RFC   ) = 1;
436     }
437     if(ui32Domains & PRCM_DOMAIN_SERIAL)
438     {
439         HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_PDCTL0SERIAL) = 1;
440     }
441     if(ui32Domains & PRCM_DOMAIN_PERIPH)
442     {
443         HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_PDCTL0PERIPH) = 1;
444     }
445     if(ui32Domains & PRCM_DOMAIN_VIMS)
446     {
447         HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_PDCTL1VIMS  ) = 1;
448     }
449     if(ui32Domains & PRCM_DOMAIN_CPU)
450     {
451         HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_PDCTL1CPU   ) = 1;
452     }
453 }
454 
455 //*****************************************************************************
456 //
457 // Turn off a specific power domain
458 //
459 //*****************************************************************************
460 void
PRCMPowerDomainOff(uint32_t ui32Domains)461 PRCMPowerDomainOff(uint32_t ui32Domains)
462 {
463     // Check the arguments.
464     ASSERT((ui32Domains & PRCM_DOMAIN_RFCORE) ||
465            (ui32Domains & PRCM_DOMAIN_SERIAL) ||
466            (ui32Domains & PRCM_DOMAIN_PERIPH) ||
467            (ui32Domains & PRCM_DOMAIN_CPU) ||
468            (ui32Domains & PRCM_DOMAIN_VIMS));
469 
470     // Assert the request to power off the right domains.
471     if(ui32Domains & PRCM_DOMAIN_RFCORE)
472     {
473         HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_PDCTL0RFC   ) = 0;
474     }
475     if(ui32Domains & PRCM_DOMAIN_SERIAL)
476     {
477         HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_PDCTL0SERIAL) = 0;
478     }
479     if(ui32Domains & PRCM_DOMAIN_PERIPH)
480     {
481         HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_PDCTL0PERIPH) = 0;
482     }
483     if(ui32Domains & PRCM_DOMAIN_VIMS)
484     {
485         // Write bits ui32Domains[17:16] to the VIMS_MODE alias register.
486         // PRCM_DOMAIN_VIMS sets VIMS_MODE=0b00, PRCM_DOMAIN_VIMS_OFF_NO_WAKEUP sets VIMS_MODE=0b10.
487         ASSERT(!(ui32Domains & 0x00010000));
488         HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_PDCTL1VIMS  ) = ( ui32Domains >> 16 ) & 3;
489     }
490     if(ui32Domains & PRCM_DOMAIN_CPU)
491     {
492         HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_PDCTL1CPU   ) = 0;
493     }
494 }
495 
496 //*****************************************************************************
497 //
498 // Enables a peripheral in Run mode
499 //
500 //*****************************************************************************
501 void
PRCMPeripheralRunEnable(uint32_t ui32Peripheral)502 PRCMPeripheralRunEnable(uint32_t ui32Peripheral)
503 {
504     // Check the arguments.
505     ASSERT(PRCMPeripheralValid(ui32Peripheral));
506 
507     // Enable module in Run Mode.
508     HWREG(g_pui32RCGCRegs[PRCM_PERIPH_INDEX(ui32Peripheral)]) |=
509         PRCM_PERIPH_MASKBIT(ui32Peripheral);
510 }
511 
512 //*****************************************************************************
513 //
514 // Disables a peripheral in Run mode
515 //
516 //*****************************************************************************
517 void
PRCMPeripheralRunDisable(uint32_t ui32Peripheral)518 PRCMPeripheralRunDisable(uint32_t ui32Peripheral)
519 {
520     // Check the arguments.
521     ASSERT(PRCMPeripheralValid(ui32Peripheral));
522 
523     // Disable module in Run Mode.
524     HWREG(g_pui32RCGCRegs[PRCM_PERIPH_INDEX(ui32Peripheral)]) &=
525         ~PRCM_PERIPH_MASKBIT(ui32Peripheral);
526 }
527 
528 //*****************************************************************************
529 //
530 // Enables a peripheral in sleep mode
531 //
532 //*****************************************************************************
533 void
PRCMPeripheralSleepEnable(uint32_t ui32Peripheral)534 PRCMPeripheralSleepEnable(uint32_t ui32Peripheral)
535 {
536     // Check the arguments.
537     ASSERT(PRCMPeripheralValid(ui32Peripheral));
538 
539     // Enable this peripheral in sleep mode.
540     HWREG(g_pui32SCGCRegs[PRCM_PERIPH_INDEX(ui32Peripheral)]) |=
541         PRCM_PERIPH_MASKBIT(ui32Peripheral);
542 }
543 
544 //*****************************************************************************
545 //
546 // Disables a peripheral in sleep mode
547 //
548 //*****************************************************************************
549 void
PRCMPeripheralSleepDisable(uint32_t ui32Peripheral)550 PRCMPeripheralSleepDisable(uint32_t ui32Peripheral)
551 {
552     // Check the arguments.
553     ASSERT(PRCMPeripheralValid(ui32Peripheral));
554 
555     // Disable this peripheral in sleep mode
556     HWREG(g_pui32SCGCRegs[PRCM_PERIPH_INDEX(ui32Peripheral)]) &=
557         ~PRCM_PERIPH_MASKBIT(ui32Peripheral);
558 }
559 
560 //*****************************************************************************
561 //
562 // Enables a peripheral in deep-sleep mode
563 //
564 //*****************************************************************************
565 void
PRCMPeripheralDeepSleepEnable(uint32_t ui32Peripheral)566 PRCMPeripheralDeepSleepEnable(uint32_t ui32Peripheral)
567 {
568     // Check the arguments.
569     ASSERT(PRCMPeripheralValid(ui32Peripheral));
570 
571     // Enable this peripheral in deep-sleep mode.
572     HWREG(g_pui32DCGCRegs[PRCM_PERIPH_INDEX(ui32Peripheral)]) |=
573         PRCM_PERIPH_MASKBIT(ui32Peripheral);
574 }
575 
576 //*****************************************************************************
577 //
578 // Disables a peripheral in deep-sleep mode
579 //
580 //*****************************************************************************
581 void
PRCMPeripheralDeepSleepDisable(uint32_t ui32Peripheral)582 PRCMPeripheralDeepSleepDisable(uint32_t ui32Peripheral)
583 {
584     // Check the arguments.
585     ASSERT(PRCMPeripheralValid(ui32Peripheral));
586 
587     // Disable this peripheral in Deep Sleep mode.
588     HWREG(g_pui32DCGCRegs[PRCM_PERIPH_INDEX(ui32Peripheral)]) &=
589         ~PRCM_PERIPH_MASKBIT(ui32Peripheral);
590 }
591 
592 //*****************************************************************************
593 //
594 // Return PRCM_DOMAIN_POWER_OFF if all power domains are off
595 //
596 //*****************************************************************************
597 uint32_t
PRCMPowerDomainsAllOff(uint32_t ui32Domains)598 PRCMPowerDomainsAllOff(uint32_t ui32Domains)
599 {
600     bool bStatus;
601     uint32_t ui32StatusRegister0;
602     uint32_t ui32StatusRegister1;
603 
604     // Check the arguments.
605     ASSERT((ui32Domains & (PRCM_DOMAIN_RFCORE |
606                            PRCM_DOMAIN_SERIAL |
607                            PRCM_DOMAIN_PERIPH)));
608 
609     bStatus = false;
610     ui32StatusRegister0 = HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_PDSTAT0);
611     ui32StatusRegister1 = HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_PDSTAT1);
612 
613     // Return the correct power status.
614     if(ui32Domains & PRCM_DOMAIN_RFCORE)
615     {
616        bStatus = bStatus ||
617                  ((ui32StatusRegister0 & PRCM_PDSTAT0_RFC_ON) ||
618                   (ui32StatusRegister1 & PRCM_PDSTAT1_RFC_ON));
619     }
620     if(ui32Domains & PRCM_DOMAIN_SERIAL)
621     {
622         bStatus = bStatus || (ui32StatusRegister0 & PRCM_PDSTAT0_SERIAL_ON);
623     }
624     if(ui32Domains & PRCM_DOMAIN_PERIPH)
625     {
626         bStatus = bStatus || (ui32StatusRegister0 & PRCM_PDSTAT0_PERIPH_ON);
627     }
628 
629     // Return the status.
630     return (bStatus ? PRCM_DOMAIN_POWER_ON : PRCM_DOMAIN_POWER_OFF);
631 }
632 
633 //*****************************************************************************
634 //
635 // Return PRCM_DOMAIN_POWER_ON if all power domains are on
636 //
637 //*****************************************************************************
638 uint32_t
PRCMPowerDomainsAllOn(uint32_t ui32Domains)639 PRCMPowerDomainsAllOn(uint32_t ui32Domains)
640 {
641     bool bStatus;
642     uint32_t ui32StatusRegister0;
643     uint32_t ui32StatusRegister1;
644 
645     // Check the arguments.
646     ASSERT((ui32Domains & (PRCM_DOMAIN_RFCORE |
647                            PRCM_DOMAIN_SERIAL |
648                            PRCM_DOMAIN_PERIPH)));
649 
650     bStatus = true;
651     ui32StatusRegister0 = HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_PDSTAT0);
652     ui32StatusRegister1 = HWREG(PRCM_BASE + NONSECURE_OFFSET + PRCM_O_PDSTAT1);
653 
654     // Return the correct power status.
655     if(ui32Domains & PRCM_DOMAIN_RFCORE)
656     {
657        bStatus = bStatus &&
658                  ((ui32StatusRegister0 & PRCM_PDSTAT0_RFC_ON) ||
659                   (ui32StatusRegister1 & PRCM_PDSTAT1_RFC_ON));
660     }
661     if(ui32Domains & PRCM_DOMAIN_SERIAL)
662     {
663         bStatus = bStatus && (ui32StatusRegister0 & PRCM_PDSTAT0_SERIAL_ON);
664     }
665     if(ui32Domains & PRCM_DOMAIN_PERIPH)
666     {
667         bStatus = bStatus && (ui32StatusRegister0 & PRCM_PDSTAT0_PERIPH_ON);
668     }
669 
670     // Return the status.
671     return (bStatus ? PRCM_DOMAIN_POWER_ON : PRCM_DOMAIN_POWER_OFF);
672 }
673 
674 //*****************************************************************************
675 //
676 // Put the processor into deep-sleep mode
677 //
678 //*****************************************************************************
679 void
PRCMDeepSleep(void)680 PRCMDeepSleep(void)
681 {
682     // Enable deep-sleep.
683     HWREG(NVIC_SYS_CTRL) |= NVIC_SYS_CTRL_SLEEPDEEP;
684 
685     // Wait for an interrupt.
686     CPUwfi();
687 
688     // Disable deep-sleep so that a future sleep will work correctly.
689     HWREG(NVIC_SYS_CTRL) &= ~(NVIC_SYS_CTRL_SLEEPDEEP);
690 }
691