1 //*****************************************************************************
2 //
3 //! @file am_hal_pwrctrl.c
4 //!
5 //! @brief Functions for enabling and disabling power domains.
6 //!
7 //! @addtogroup pwrctrl4_4p PWRCTRL - Power Control
8 //! @ingroup apollo4p_hal
9 //! @{
10 //
11 //*****************************************************************************
12 
13 //*****************************************************************************
14 //
15 // Copyright (c) 2023, Ambiq Micro, Inc.
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are met:
20 //
21 // 1. Redistributions of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimer.
23 //
24 // 2. Redistributions in binary form must reproduce the above copyright
25 // notice, this list of conditions and the following disclaimer in the
26 // documentation and/or other materials provided with the distribution.
27 //
28 // 3. Neither the name of the copyright holder nor the names of its
29 // contributors may be used to endorse or promote products derived from this
30 // software without specific prior written permission.
31 //
32 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
36 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 // POSSIBILITY OF SUCH DAMAGE.
43 //
44 // This is part of revision release_sdk_4_4_0-3c5977e664 of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47 #include <stdint.h>
48 #include <stdbool.h>
49 #include "am_mcu_apollo.h"
50 
51 //*****************************************************************************
52 //
53 // Local defines
54 //
55 //*****************************************************************************
56 
57 //
58 //! Maximum number of checks to memory power status before declaring error
59 // (5 x 1usec = 5usec).
60 //
61 #define AM_HAL_PWRCTRL_MAX_WAIT_US      5
62 
63 
64 #define AM_HAL_PWRCTRL_MEMPWREN_MASK    ( PWRCTRL_MEMPWREN_PWRENDTCM_Msk        |   \
65                                           PWRCTRL_MEMPWREN_PWRENNVM0_Msk        |   \
66                                           PWRCTRL_MEMPWREN_PWRENCACHEB0_Msk     |   \
67                                           PWRCTRL_MEMPWREN_PWRENCACHEB2_Msk )
68 
69 #define AM_HAL_PWRCTRL_DSPMEMPWRST_MASK ( PWRCTRL_DSP0MEMPWRST_PWRSTDSP0RAM_Msk |   \
70                                           PWRCTRL_DSP0MEMPWRST_PWRSTDSP0ICACHE_Msk )
71 
72 //
73 //! "PCM" is simply a trim level version of product test.
74 //
75 #define TRIMREV_PCM             3   // Trim revision number for PCM
76 
77 //
78 //! Trim revision 6 is required for the following pwrctrl adjustments:
79 //!  - Sourcing MCUH from the VDDC_LV rail
80 //!  - Reliable application of TempCo
81 //!  - Applying Crypto boosts
82 //
83 #define TRIMREV_PWRCTRL         6
84 
85 //*****************************************************************************
86 //
87 //! @name Define max values of some useful fields
88 //! @{
89 //
90 // ****************************************************************************
91 #define MAX_ACTTRIMVDDF         _FLD2VAL(MCUCTRL_SIMOBUCK12_ACTTRIMVDDF, 0xFFFFFFFF)    // Buck VDDF
92 #define MAX_MEMLDOACTIVETRIM    _FLD2VAL(MCUCTRL_LDOREG2_MEMLDOACTIVETRIM, 0xFFFFFFFF)  // LDO VDDF
93 #define MAX_LPTRIMVDDF          _FLD2VAL(MCUCTRL_SIMOBUCK12_LPTRIMVDDF, 0xFFFFFFFF)     // VDDF LP
94 #define MAX_MEMLPLDOTRIM        _FLD2VAL(MCUCTRL_LDOREG2_MEMLPLDOTRIM, 0xFFFFFFFF)      // MEM LP LDO
95 #define MAX_TVRGVREFTRIM        _FLD2VAL(MCUCTRL_VREFGEN2_TVRGVREFTRIM, 0xFFFFFFFF)     // Buck VDDC
96 #define MAX_CORELDOACTIVETRIM   _FLD2VAL(MCUCTRL_LDOREG1_CORELDOACTIVETRIM, 0xFFFFFFFF) // Buck VDDC
97 //! @}
98 
99 //
100 // Internal non-published function, since Timer13 is reserved for a workaround.
101 //
102 extern uint32_t internal_timer_config(uint32_t ui32TimerNumber,
103                                       am_hal_timer_config_t *psTimerConfig);
104 
105 // ****************************************************************************
106 //
107 // Global variables.
108 //
109 // ****************************************************************************
110 
111 //*****************************************************************************
112 //
113 //! @name Global State Variables for the VDDF and VDDC boosting
114 //! @{
115 //
116 // ****************************************************************************
117 am_hal_pwrctrl_mcu_mode_e g_eCurrPwrMode    = AM_HAL_PWRCTRL_MCU_MODE_LOW_POWER;
118 uint32_t g_ui32TrimVer                      = 0xFFFFFFFF;
119 uint32_t g_ui32origSimobuckVDDStrim         = 0xFFFFFFFF;
120 //! @}
121 
122 //*****************************************************************************
123 //
124 //! @name Save factory trim values.
125 //! @{
126 //
127 // ****************************************************************************
128 static bool     g_bOrigTrimsStored          = false;
129 static uint32_t g_orig_ACTTRIMVDDF          = 0;
130 static uint32_t g_orig_MEMLDOACTIVETRIM     = 0;
131 static uint32_t g_orig_LPTRIMVDDF           = 0;
132 static uint32_t g_orig_MEMLPLDOTRIM         = 0;
133 static uint32_t g_orig_TVRGVREFTRIM         = 0;
134 static uint32_t g_orig_CORELDOACTIVETRIM    = 0;
135 //! @}
136 
137 #if AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
138 //*****************************************************************************
139 //
140 //! @name Trim state variables
141 //! @{
142 //
143 // ****************************************************************************
144 static uint32_t g_ui32VDDFAdjustCodes       = 0;
145 static  int32_t g_i32LatestVddfActTrim      = 0;
146 static  int32_t g_i32LatestLDOActTrim       = 0;
147 static bool     g_bBoostForCryptoApplied    = false;
148 //
149 //! @}
150 //
151 #endif // AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
152 
153 #if AM_HAL_TEMPCO_LP
154 //*****************************************************************************
155 //
156 //! @name Saved handle and slot number for TempCo.
157 //! @{
158 //
159 // ****************************************************************************
160 static void    *g_TempcoADCHandle;
161 static uint32_t g_ui32TempcoADCslot;
162 static uint16_t g_ui16TempcoTEMP_code;
163 static bool     g_bTempcoValid           = false;
164 static float    g_pfTempMeasured;
165 //
166 //! @}
167 //
168 #endif // AM_HAL_TEMPCO_LP
169 
170 //*****************************************************************************
171 //
172 //! @name DEVPWREN and DEVPWRSTATUS Mask Macros
173 //! @{
174 //! The below DEVPWREN and DEVPWRSTATUS masks are used to check if a peripheral
175 //!    has been disabled properly
176 //!
177 //! The original check of ((PWRCTRL->DEVPWRSTATUS & ui32PeriphStatus) == 0)
178 //!     will fail when more than one enable in the same domain is set and the
179 //!     user tries disable only one.
180 // ****************************************************************************
181 
182 #define PWRCTRL_HCPB_DEVPWREN_MASK       ( \
183     _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM0, PWRCTRL_DEVPWREN_PWRENIOM0_EN) | \
184     _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM1, PWRCTRL_DEVPWREN_PWRENIOM1_EN) | \
185     _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM2, PWRCTRL_DEVPWREN_PWRENIOM2_EN) | \
186     _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM3, PWRCTRL_DEVPWREN_PWRENIOM3_EN))
187 
188 #define PWRCTRL_HCPC_DEVPWREN_MASK       ( \
189     _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM4, PWRCTRL_DEVPWREN_PWRENIOM4_EN) | \
190     _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM5, PWRCTRL_DEVPWREN_PWRENIOM5_EN) | \
191     _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM6, PWRCTRL_DEVPWREN_PWRENIOM6_EN) | \
192     _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM7, PWRCTRL_DEVPWREN_PWRENIOM7_EN))
193 
194 #define PWRCTRL_HCPA_DEVPWREN_MASK       ( \
195     _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUART0, PWRCTRL_DEVPWREN_PWRENUART0_EN) | \
196     _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUART1, PWRCTRL_DEVPWREN_PWRENUART1_EN) | \
197     _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUART2, PWRCTRL_DEVPWREN_PWRENUART2_EN) | \
198     _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUART3, PWRCTRL_DEVPWREN_PWRENUART3_EN))
199 
200 #define PWRCTRL_MSPI_DEVPWREN_MASK       ( \
201     _VAL2FLD(PWRCTRL_DEVPWREN_PWRENMSPI0, PWRCTRL_DEVPWREN_PWRENMSPI0_EN) | \
202     _VAL2FLD(PWRCTRL_DEVPWREN_PWRENMSPI1, PWRCTRL_DEVPWREN_PWRENMSPI1_EN) | \
203     _VAL2FLD(PWRCTRL_DEVPWREN_PWRENMSPI2, PWRCTRL_DEVPWREN_PWRENMSPI2_EN))
204 
205 #define PWRCTRL_AUD_DEVPWREN_MASK       ( \
206     _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENAUDREC, PWRCTRL_AUDSSPWREN_PWRENAUDREC_EN) | \
207     _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENAUDPB, PWRCTRL_AUDSSPWREN_PWRENAUDPB_EN)   | \
208     _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENPDM0, PWRCTRL_AUDSSPWREN_PWRENPDM0_EN)     | \
209     _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENPDM1, PWRCTRL_AUDSSPWREN_PWRENPDM1_EN)     | \
210     _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENPDM2, PWRCTRL_AUDSSPWREN_PWRENPDM2_EN)     | \
211     _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENPDM3, PWRCTRL_AUDSSPWREN_PWRENPDM3_EN)     | \
212     _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENI2S0, PWRCTRL_AUDSSPWREN_PWRENI2S0_EN)     | \
213     _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENI2S1, PWRCTRL_AUDSSPWREN_PWRENI2S1_EN))
214 
215 #define PWRCTRL_HCPB_DEVPWRSTATUS_MASK      ( \
216     PWRCTRL_DEVPWRSTATUS_PWRSTIOM0_Msk | \
217     PWRCTRL_DEVPWRSTATUS_PWRSTIOM1_Msk | \
218     PWRCTRL_DEVPWRSTATUS_PWRSTIOM2_Msk | \
219     PWRCTRL_DEVPWRSTATUS_PWRSTIOM3_Msk)
220 
221 #define PWRCTRL_HCPC_DEVPWRSTATUS_MASK      ( \
222     PWRCTRL_DEVPWRSTATUS_PWRSTIOM4_Msk | \
223     PWRCTRL_DEVPWRSTATUS_PWRSTIOM5_Msk | \
224     PWRCTRL_DEVPWRSTATUS_PWRSTIOM6_Msk | \
225     PWRCTRL_DEVPWRSTATUS_PWRSTIOM7_Msk)
226 
227 #define PWRCTRL_HCPA_DEVPWRSTATUS_MASK          ( \
228     PWRCTRL_DEVPWRSTATUS_PWRSTUART0_Msk | \
229     PWRCTRL_DEVPWRSTATUS_PWRSTUART1_Msk | \
230     PWRCTRL_DEVPWRSTATUS_PWRSTUART2_Msk | \
231     PWRCTRL_DEVPWRSTATUS_PWRSTUART3_Msk)
232 
233 #define PWRCTRL_MSPI_DEVPWRSTATUS_MASK          ( \
234     PWRCTRL_DEVPWRSTATUS_PWRSTMSPI0_Msk | \
235     PWRCTRL_DEVPWRSTATUS_PWRSTMSPI1_Msk | \
236     PWRCTRL_DEVPWRSTATUS_PWRSTMSPI2_Msk)
237 
238 #define PWRCTRL_AUD_DEVPWRSTATUS_MASK      ( \
239     PWRCTRL_AUDSSPWRSTATUS_PWRSTAUDREC_Msk | \
240     PWRCTRL_AUDSSPWRSTATUS_PWRSTAUDPB_Msk  | \
241     PWRCTRL_AUDSSPWRSTATUS_PWRSTPDM0_Msk   | \
242     PWRCTRL_AUDSSPWRSTATUS_PWRSTPDM1_Msk   | \
243     PWRCTRL_AUDSSPWRSTATUS_PWRSTPDM2_Msk   | \
244     PWRCTRL_AUDSSPWRSTATUS_PWRSTPDM3_Msk   | \
245     PWRCTRL_AUDSSPWRSTATUS_PWRSTI2S0_Msk   | \
246     PWRCTRL_AUDSSPWRSTATUS_PWRSTI2S1_Msk)
247 //! @}
248 
249 // **********************************************
250 //! Define the peripheral control structure.
251 // **********************************************
252 struct am_pwr_s
253 {
254     uint32_t    ui32PwrEnRegAddr;
255     uint32_t    ui32PeriphEnable;
256     uint32_t    ui32PwrStatReqAddr;
257     uint32_t    ui32PeriphStatus;
258 };
259 
260 //
261 //! Peripheral control data structure
262 //
263 #ifndef AM_HAL_PWRCTRL_RAM_TABLE
264 const struct am_pwr_s am_hal_pwrctrl_peripheral_control[AM_HAL_PWRCTRL_PERIPH_MAX] =
265 {
266     {
267         AM_REGADDR(PWRCTRL, DEVPWREN),
268         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOS, PWRCTRL_DEVPWREN_PWRENIOS_EN),
269         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
270         PWRCTRL_DEVPWRSTATUS_PWRSTIOS_Msk
271     },
272     {
273         AM_REGADDR(PWRCTRL, DEVPWREN),
274         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM0, PWRCTRL_DEVPWREN_PWRENIOM0_EN),
275         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
276         PWRCTRL_HCPB_DEVPWRSTATUS_MASK
277     },
278     {
279         AM_REGADDR(PWRCTRL, DEVPWREN),
280         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM1, PWRCTRL_DEVPWREN_PWRENIOM1_EN),
281         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
282         PWRCTRL_HCPB_DEVPWRSTATUS_MASK
283     },
284     {
285         AM_REGADDR(PWRCTRL, DEVPWREN),
286         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM2, PWRCTRL_DEVPWREN_PWRENIOM2_EN),
287         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
288         PWRCTRL_HCPB_DEVPWRSTATUS_MASK
289     },
290     {
291         AM_REGADDR(PWRCTRL, DEVPWREN),
292         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM3, PWRCTRL_DEVPWREN_PWRENIOM3_EN),
293         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
294         PWRCTRL_HCPB_DEVPWRSTATUS_MASK
295     },
296     {
297         AM_REGADDR(PWRCTRL, DEVPWREN),
298         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM4, PWRCTRL_DEVPWREN_PWRENIOM4_EN),
299         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
300         PWRCTRL_HCPC_DEVPWRSTATUS_MASK
301     },
302     {
303         AM_REGADDR(PWRCTRL, DEVPWREN),
304         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM5, PWRCTRL_DEVPWREN_PWRENIOM5_EN),
305         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
306         PWRCTRL_HCPC_DEVPWRSTATUS_MASK
307     },
308     {
309         AM_REGADDR(PWRCTRL, DEVPWREN),
310         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM6, PWRCTRL_DEVPWREN_PWRENIOM6_EN),
311         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
312         PWRCTRL_HCPC_DEVPWRSTATUS_MASK
313     },
314     {
315         AM_REGADDR(PWRCTRL, DEVPWREN),
316         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM7, PWRCTRL_DEVPWREN_PWRENIOM7_EN),
317         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
318         PWRCTRL_HCPC_DEVPWRSTATUS_MASK
319     },
320     {
321         AM_REGADDR(PWRCTRL, DEVPWREN),
322         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUART0, PWRCTRL_DEVPWREN_PWRENUART0_EN),
323         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
324         PWRCTRL_HCPA_DEVPWRSTATUS_MASK
325     },
326     {
327         AM_REGADDR(PWRCTRL, DEVPWREN),
328         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUART1, PWRCTRL_DEVPWREN_PWRENUART1_EN),
329         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
330         PWRCTRL_HCPA_DEVPWRSTATUS_MASK
331     },
332     {
333         AM_REGADDR(PWRCTRL, DEVPWREN),
334         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUART2, PWRCTRL_DEVPWREN_PWRENUART2_EN),
335         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
336         PWRCTRL_HCPA_DEVPWRSTATUS_MASK
337     },
338     {
339         AM_REGADDR(PWRCTRL, DEVPWREN),
340         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUART3, PWRCTRL_DEVPWREN_PWRENUART3_EN),
341         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
342         PWRCTRL_HCPA_DEVPWRSTATUS_MASK
343     },
344     {
345         AM_REGADDR(PWRCTRL, DEVPWREN),
346         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENADC, PWRCTRL_DEVPWREN_PWRENADC_EN),
347         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
348         PWRCTRL_DEVPWRSTATUS_PWRSTADC_Msk
349     },
350     {
351         AM_REGADDR(PWRCTRL, DEVPWREN),
352         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENMSPI0, PWRCTRL_DEVPWREN_PWRENMSPI0_EN),
353         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
354         PWRCTRL_MSPI_DEVPWRSTATUS_MASK
355     },
356     {
357         AM_REGADDR(PWRCTRL, DEVPWREN),
358         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENMSPI1, PWRCTRL_DEVPWREN_PWRENMSPI1_EN),
359         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
360         PWRCTRL_MSPI_DEVPWRSTATUS_MASK
361     },
362     {
363         AM_REGADDR(PWRCTRL, DEVPWREN),
364         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENMSPI2, PWRCTRL_DEVPWREN_PWRENMSPI2_EN),
365         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
366         PWRCTRL_MSPI_DEVPWRSTATUS_MASK
367     },
368     {
369         AM_REGADDR(PWRCTRL, DEVPWREN),
370         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENGFX, PWRCTRL_DEVPWREN_PWRENGFX_EN),
371         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
372         PWRCTRL_DEVPWRSTATUS_PWRSTGFX_Msk
373     },
374     {
375         AM_REGADDR(PWRCTRL, DEVPWREN),
376         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENDISP, PWRCTRL_DEVPWREN_PWRENDISP_EN),
377         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
378         PWRCTRL_DEVPWRSTATUS_PWRSTDISP_Msk
379     },
380     {
381         AM_REGADDR(PWRCTRL, DEVPWREN),
382         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENDISPPHY, PWRCTRL_DEVPWREN_PWRENDISPPHY_EN),
383         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
384         PWRCTRL_DEVPWRSTATUS_PWRSTDISPPHY_Msk
385     },
386     {
387         AM_REGADDR(PWRCTRL, DEVPWREN),
388         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENCRYPTO, PWRCTRL_DEVPWREN_PWRENCRYPTO_EN),
389         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
390         PWRCTRL_DEVPWRSTATUS_PWRSTCRYPTO_Msk
391     },
392     {
393         AM_REGADDR(PWRCTRL, DEVPWREN),
394         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENSDIO, PWRCTRL_DEVPWREN_PWRENSDIO_EN),
395         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
396         PWRCTRL_DEVPWRSTATUS_PWRSTSDIO_Msk
397     },
398     {
399         AM_REGADDR(PWRCTRL, DEVPWREN),
400         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUSB, PWRCTRL_DEVPWREN_PWRENUSB_EN),
401         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
402         PWRCTRL_DEVPWRSTATUS_PWRSTUSB_Msk
403     },
404     {
405         AM_REGADDR(PWRCTRL, DEVPWREN),
406         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUSBPHY, PWRCTRL_DEVPWREN_PWRENUSBPHY_EN),
407         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
408         PWRCTRL_DEVPWRSTATUS_PWRSTUSBPHY_Msk
409     },
410     {
411         AM_REGADDR(PWRCTRL, DEVPWREN),
412         _VAL2FLD(PWRCTRL_DEVPWREN_PWRENDBG, PWRCTRL_DEVPWREN_PWRENDBG_EN),
413         AM_REGADDR(PWRCTRL, DEVPWRSTATUS),
414         PWRCTRL_DEVPWRSTATUS_PWRSTDBG_Msk
415     },
416     {
417         AM_REGADDR(PWRCTRL, AUDSSPWREN),
418         _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENAUDREC, PWRCTRL_AUDSSPWREN_PWRENAUDREC_EN),
419         AM_REGADDR(PWRCTRL, AUDSSPWRSTATUS),
420         PWRCTRL_AUD_DEVPWRSTATUS_MASK
421     },
422     {
423         AM_REGADDR(PWRCTRL, AUDSSPWREN),
424         _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENAUDPB, PWRCTRL_AUDSSPWREN_PWRENAUDPB_EN),
425         AM_REGADDR(PWRCTRL, AUDSSPWRSTATUS),
426         PWRCTRL_AUD_DEVPWRSTATUS_MASK
427     },
428     {
429         AM_REGADDR(PWRCTRL, AUDSSPWREN),
430         _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENPDM0, PWRCTRL_AUDSSPWREN_PWRENPDM0_EN),
431         AM_REGADDR(PWRCTRL, AUDSSPWRSTATUS),
432         PWRCTRL_AUD_DEVPWRSTATUS_MASK
433     },
434     {
435         AM_REGADDR(PWRCTRL, AUDSSPWREN),
436         _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENPDM1, PWRCTRL_AUDSSPWREN_PWRENPDM1_EN),
437         AM_REGADDR(PWRCTRL, AUDSSPWRSTATUS),
438         PWRCTRL_AUD_DEVPWRSTATUS_MASK
439     },
440     {
441         AM_REGADDR(PWRCTRL, AUDSSPWREN),
442         _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENPDM2, PWRCTRL_AUDSSPWREN_PWRENPDM2_EN),
443         AM_REGADDR(PWRCTRL, AUDSSPWRSTATUS),
444         PWRCTRL_AUD_DEVPWRSTATUS_MASK
445     },
446     {
447         AM_REGADDR(PWRCTRL, AUDSSPWREN),
448         _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENPDM3, PWRCTRL_AUDSSPWREN_PWRENPDM3_EN),
449         AM_REGADDR(PWRCTRL, AUDSSPWRSTATUS),
450         PWRCTRL_AUD_DEVPWRSTATUS_MASK
451     },
452     {
453         AM_REGADDR(PWRCTRL, AUDSSPWREN),
454         _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENI2S0, PWRCTRL_AUDSSPWREN_PWRENI2S0_EN),
455         AM_REGADDR(PWRCTRL, AUDSSPWRSTATUS),
456         PWRCTRL_AUD_DEVPWRSTATUS_MASK
457     },
458     {
459         AM_REGADDR(PWRCTRL, AUDSSPWREN),
460         _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENI2S1, PWRCTRL_AUDSSPWREN_PWRENI2S1_EN),
461         AM_REGADDR(PWRCTRL, AUDSSPWRSTATUS),
462         PWRCTRL_AUD_DEVPWRSTATUS_MASK
463     },
464     {
465         AM_REGADDR(PWRCTRL, AUDSSPWREN),
466         _VAL2FLD(PWRCTRL_AUDSSPWREN_PWRENAUDADC, PWRCTRL_AUDSSPWREN_PWRENAUDADC_EN),
467         AM_REGADDR(PWRCTRL, AUDSSPWRSTATUS),
468         PWRCTRL_AUDSSPWRSTATUS_PWRSTAUDADC_Msk
469     },
470 };
471 
472 //*****************************************************************************
473 //
474 //! @brief  Return the pwr_ctrl entry for a given ePeripheral
475 //!
476 //! @param  pwr_ctrl address where the power entry is copied
477 //! @param  ePeripheral the peripheral to copy
478 //!
479 //! @return Returns AM_HAL_STATUS_SUCCESS on success
480 //
481 //*****************************************************************************
482 static inline uint32_t
am_get_pwrctrl(struct am_pwr_s * pwr_ctrl,uint32_t ePeripheral)483 am_get_pwrctrl(struct am_pwr_s *pwr_ctrl, uint32_t ePeripheral)
484 {
485     if ( pwr_ctrl == NULL || ePeripheral >= AM_HAL_PWRCTRL_PERIPH_MAX )
486     {
487         return AM_HAL_STATUS_INVALID_ARG;
488     }
489 
490     *pwr_ctrl = am_hal_pwrctrl_peripheral_control[ePeripheral];
491 
492     return AM_HAL_STATUS_SUCCESS;
493 }
494 #else
495 //*****************************************************************************
496 //
497 //! @brief  Return the pwr_ctrl entry for a given ePeripheral
498 //!
499 //! @param  pwr_ctrl address where the power entry is generated
500 //! @param  ePeripheral the peripheral for which to generate:
501 //!
502 //! @return Returns AM_HAL_STATUS_SUCCESS on success
503 //
504 //*****************************************************************************
505 static uint32_t
am_get_pwrctrl(struct am_pwr_s * pwr_ctrl,uint32_t ePeripheral)506 am_get_pwrctrl(struct am_pwr_s *pwr_ctrl, uint32_t ePeripheral)
507 {
508     int shift_pos;
509 
510     if (pwr_ctrl == NULL || ePeripheral >= AM_HAL_PWRCTRL_PERIPH_MAX)
511     {
512         return AM_HAL_STATUS_INVALID_ARG;
513     }
514 
515     if (ePeripheral < AM_HAL_PWRCTRL_PERIPH_AUDREC)
516     {
517         pwr_ctrl->ui32PwrEnRegAddr = AM_REGADDR(PWRCTRL, DEVPWREN);
518         pwr_ctrl->ui32PwrStatReqAddr = AM_REGADDR(PWRCTRL, DEVPWRSTATUS);
519         pwr_ctrl->ui32PeriphEnable = 1 << ePeripheral;
520         pwr_ctrl->ui32PeriphStatus = 1 << ePeripheral;
521     }
522     else
523     {
524         shift_pos = (ePeripheral - AM_HAL_PWRCTRL_PERIPH_AUDREC);
525         if (ePeripheral > AM_HAL_PWRCTRL_PERIPH_I2S1)
526         {
527             shift_pos += 2;
528         }
529 
530         pwr_ctrl->ui32PwrEnRegAddr =  AM_REGADDR(PWRCTRL, AUDSSPWREN);
531         pwr_ctrl->ui32PwrStatReqAddr = AM_REGADDR(PWRCTRL, AUDSSPWRSTATUS);
532         pwr_ctrl->ui32PeriphEnable = 1 << shift_pos;
533         pwr_ctrl->ui32PeriphStatus = 1 << shift_pos;
534     }
535 
536     return AM_HAL_STATUS_SUCCESS;
537 }
538 #endif // AM_HAL_PWRCTRL_RAM_TABLE
539 
540 //*****************************************************************************
541 //
542 // Default configurations definitions
543 //
544 //*****************************************************************************
545 const am_hal_pwrctrl_mcu_memory_config_t    g_DefaultMcuMemCfg =
546 {
547     .eCacheCfg          = AM_HAL_PWRCTRL_CACHE_ALL,
548     .bRetainCache       = true,
549     .eDTCMCfg           = AM_HAL_PWRCTRL_DTCM_384K,
550     .eRetainDTCM        = AM_HAL_PWRCTRL_DTCM_384K,
551     .bEnableNVM0        = true,
552     .bRetainNVM0        = false
553 };
554 
555 const am_hal_pwrctrl_sram_memcfg_t          g_DefaultSRAMCfg =
556 {
557     //
558     //! Default configuration for Shared SRAM:
559     //! Enable all SSRAM
560     //! All active bits = 0.
561     //!   Active bits 0 allow memory to go to retention in deepsleep.
562     //!   Active bits 1 force the memory to stay on, requiring more power.
563     //! Retain all SSRAM in deepsleep.
564     //
565     .eSRAMCfg           = AM_HAL_PWRCTRL_SRAM_ALL,
566     .eActiveWithMCU     = AM_HAL_PWRCTRL_SRAM_NONE,
567     .eActiveWithGFX     = AM_HAL_PWRCTRL_SRAM_NONE,
568     .eActiveWithDISP    = AM_HAL_PWRCTRL_SRAM_NONE,
569     .eActiveWithDSP     = AM_HAL_PWRCTRL_SRAM_NONE,
570     .eSRAMRetain        = AM_HAL_PWRCTRL_SRAM_ALL
571 };
572 
573 const am_hal_pwrctrl_dsp_memory_config_t    g_DefaultDSPMemCfg =
574 {
575     .bEnableICache      = false,
576     .bRetainCache       = false,
577     .bEnableRAM         = true,
578     .bActiveRAM         = false,
579     .bRetainRAM         = true
580 };
581 
582 //*****************************************************************************
583 //
584 // Function to determine the chip's TRIM version.
585 //
586 // return Status code.
587 //
588 // pui32TrimVer: The uint32_t that will receive the trim version number.
589 //               If no valid trim version found, *pui32TrimVer returns as 0.
590 //
591 //
592 //*****************************************************************************
593 static uint32_t
TrimVersionGet(uint32_t * pui32TrimVer)594 TrimVersionGet(uint32_t *pui32TrimVer)
595 {
596     uint32_t ui32Ret;
597 
598     //
599     // Get the TRIM version and set the global variable.
600     // This only needs to be done and verified once.
601     //
602     if ( g_ui32TrimVer == 0xFFFFFFFF )
603     {
604         ui32Ret = am_hal_mram_info_read(1, AM_REG_INFO1_TRIM_REV_O / 4, 1, &g_ui32TrimVer);
605 
606         if ( (ui32Ret != 0) || (g_ui32TrimVer == 0xFFFFFFFF) )
607         {
608             //
609             // Invalid trim value. Set the global to indicate version 0.
610             //
611             g_ui32TrimVer = 0;
612         }
613     }
614 
615     if ( pui32TrimVer )
616     {
617         *pui32TrimVer = g_ui32TrimVer;
618         return AM_HAL_STATUS_SUCCESS;
619     }
620     else
621     {
622         return AM_HAL_STATUS_INVALID_ARG;
623     }
624 
625 } // TrimVersionGet()
626 
627 #if defined(AM_HAL_PWRCTL_HPLP_WA)
628 //*****************************************************************************
629 //
630 // Function to initialize Timer 13 to interrupt after ui32Delayus.
631 //
632 //*****************************************************************************
633 static uint32_t
am_hal_util_write_and_wait_timer_init(uint32_t ui32Delayus)634 am_hal_util_write_and_wait_timer_init(uint32_t ui32Delayus)
635 {
636     am_hal_timer_config_t       TimerConfig;
637     uint32_t ui32Status         = AM_HAL_STATUS_SUCCESS;
638 
639     //
640     // Set the timer configuration
641     //
642     am_hal_timer_default_config_set(&TimerConfig);
643     TimerConfig.eFunction = AM_HAL_TIMER_FN_EDGE;
644     TimerConfig.ui32Compare0 = 0xFFFFFFFF;
645     TimerConfig.ui32PatternLimit = 0;
646     TimerConfig.ui32Compare1 = ui32Delayus * 6000000 / 1000000;
647     ui32Status = internal_timer_config(AM_HAL_WRITE_WAIT_TIMER, &TimerConfig);
648     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
649     {
650        return ui32Status;
651     }
652 
653     am_hal_timer_clear(AM_HAL_WRITE_WAIT_TIMER);
654     am_hal_timer_stop(AM_HAL_WRITE_WAIT_TIMER);
655 
656     //
657     // Clear the timer Interrupt
658     //
659     ui32Status = am_hal_timer_interrupt_clear(AM_HAL_TIMER_MASK(AM_HAL_WRITE_WAIT_TIMER, AM_HAL_TIMER_COMPARE1));
660     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
661     {
662         return ui32Status;
663     }
664 
665     //
666     // Enable the timer Interrupt.
667     //
668     ui32Status = am_hal_timer_interrupt_enable(AM_HAL_TIMER_MASK(AM_HAL_WRITE_WAIT_TIMER, AM_HAL_TIMER_COMPARE1));
669     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
670     {
671        return ui32Status;
672     }
673 
674     //
675     // Enable the timer interrupt in the NVIC.
676     //
677     // This interrupt needs to be set as the highest priority (0)
678     //
679     NVIC_SetPriority((IRQn_Type)((uint32_t)TIMER0_IRQn + AM_HAL_WRITE_WAIT_TIMER), 0);
680     NVIC_EnableIRQ((IRQn_Type)((uint32_t)TIMER0_IRQn + AM_HAL_WRITE_WAIT_TIMER));
681 
682     //
683     // No need to enable interrupt as we just need to get out of WFI
684     // We just need to clear the NVIC pending
685     // am_hal_interrupt_master_enable();
686     //
687 
688     return ui32Status;
689 
690 } // am_hal_util_write_and_wait_timer_init()
691 
692 //*****************************************************************************
693 //
694 // Define a simple function that will write a value to register (or other
695 // memory location) and then go to sleep.
696 // The opcodes are aligned on a 16-byte boundary to guarantee that
697 // the write and the WFI are in the same M4 line buffer.
698 //
699 //*****************************************************************************
700 //
701 // Prototype the assembly function.
702 //
703 typedef void (*storeAndWFIfunc_t)(uint32_t ui32Val, uint32_t *pAddr);
704 
705 #if (defined (__ARMCC_VERSION)) && (__ARMCC_VERSION < 6000000)
706 __align(16)
707 #define WA_ATTRIB
708 #elif (defined (__ARMCC_VERSION)) && (__ARMCC_VERSION >= 6000000)
709 #warning This attribute is not yet tested on ARM6.
710 #define WA_ATTRIB   __attribute__ ((aligned (16)))
711 #elif defined(__GNUC_STDC_INLINE__)
712 #define WA_ATTRIB   __attribute__ ((aligned (16)))
713 #elif defined(__IAR_SYSTEMS_ICC__)
714 #pragma data_alignment = 16
715 #define WA_ATTRIB
716 #else
717 #error Unknown compiler.
718 #endif
719 
720 static
721 uint16_t storeAndWFIRAM[16] WA_ATTRIB =
722 {
723     //
724     // r0: Value to be written to the location specified in the 2nd argument.
725     // r1: Address of the location to be written.
726     //
727     // Begin 1st line buffer
728     0x6008,             // str r0, [r1]
729     0xF3BF, 0x8F4F,     // DSB
730     0xBF30,             // WFI
731     0xF3BF, 0x8F6F,     // ISB
732     0x4770,             // bx lr
733     0xBF00,             // nop
734 };
735 
736 //
737 // Prototype the assembly function.
738 //
739 storeAndWFIfunc_t storeAndWFIfuncRAM = (storeAndWFIfunc_t)((uint8_t *)storeAndWFIRAM + 1);
740 
741 //*****************************************************************************
742 //
743 // am_hal_util_write_and_wait()
744 // Function to perform the RevC HP/LP mode switch.
745 //
746 //*****************************************************************************
747 uint32_t
am_hal_util_write_and_wait(uint32_t * pAddr,uint32_t ui32Mask,uint32_t ui32Val,uint32_t ui32Delayus)748 am_hal_util_write_and_wait(uint32_t *pAddr, uint32_t ui32Mask, uint32_t ui32Val, uint32_t ui32Delayus)
749 
750 {
751     uint32_t ui32Status = AM_HAL_STATUS_SUCCESS;
752     uint32_t origBasePri;
753     uint32_t basePrioGrouping;
754 
755     //
756     // Begin critical section
757     //
758     AM_CRITICAL_BEGIN
759 
760     ui32Status = am_hal_util_write_and_wait_timer_init(ui32Delayus);
761     if (ui32Status == AM_HAL_STATUS_SUCCESS)
762     {
763 
764         basePrioGrouping = NVIC_GetPriorityGrouping();
765         if (basePrioGrouping == 7)
766         {
767             //
768             // We cannot implement this workaround
769             //
770             ui32Status = AM_HAL_STATUS_FAIL;
771         }
772         else
773         {
774             //
775             // Before executing WFI as required later, flush any buffered core and peripheral writes.
776             //
777             am_hal_sysctrl_bus_write_flush();
778 
779             //
780             // Mask off all other interrupts
781             //
782             origBasePri = __get_BASEPRI();
783             if (basePrioGrouping >= (8 - __NVIC_PRIO_BITS))
784             {
785                 __set_BASEPRI(1 << (basePrioGrouping + 1));
786             }
787             else
788             {
789                 __set_BASEPRI(1 << (8 - __NVIC_PRIO_BITS));
790             }
791 
792             //
793             // Compute the value to write
794             //
795             if (ui32Mask != 0xFFFFFFFF)
796             {
797                 ui32Val |= (AM_REGVAL((uint32_t)pAddr) & ~ui32Mask);
798             }
799 
800             //
801             // Clear the timer.
802             //
803             am_hal_timer_clear(AM_HAL_WRITE_WAIT_TIMER);
804 
805             //
806             // Set for normal sleep before calling storeAndWFIfunc()
807             //
808             SCB->SCR &= ~_VAL2FLD(SCB_SCR_SLEEPDEEP, 1);
809 
810             //
811             // Call the function to switch the performance mode and WFI.
812             //
813             storeAndWFIfuncRAM(ui32Val, pAddr);
814 
815             //
816             // Stop/Disable the timer
817             //
818             am_hal_timer_stop(AM_HAL_WRITE_WAIT_TIMER);
819 
820             //
821             // Clear the timer Interrupt
822             //
823             am_hal_timer_interrupt_clear(AM_HAL_TIMER_MASK(AM_HAL_WRITE_WAIT_TIMER, AM_HAL_TIMER_COMPARE_BOTH));
824 
825             //
826             // Before clearing the NVIC pending, avoid a race condition by
827             // making sure the interrupt clear has propagated by reading
828             // the INTSTAT register.
829             //
830             volatile uint32_t ui32IntStat;
831             am_hal_timer_interrupt_status_get(true, (uint32_t*)&ui32IntStat);
832 
833             //
834             // Clear pending NVIC interrupt for the timer-specific IRQ.
835             //
836             NVIC_ClearPendingIRQ((IRQn_Type)((uint32_t)TIMER0_IRQn + AM_HAL_WRITE_WAIT_TIMER));
837 
838             //
839             // There is also a pending on the timer common IRQ. But it should
840             // only be cleared if the workaround timer is the only interrupt.
841             //
842             if ( !(ui32IntStat &
843                         ~AM_HAL_TIMER_MASK(AM_HAL_WRITE_WAIT_TIMER, AM_HAL_TIMER_COMPARE_BOTH)) )
844             {
845                 NVIC_ClearPendingIRQ(TIMER_IRQn);
846 
847                 //
848                 // One more race to consider.
849                 // If a different timer interrupt occurred while clearing the
850                 // common IRQ, set the timer common IRQ back to pending.
851                 //
852                 am_hal_timer_interrupt_status_get(true, (uint32_t*)&ui32IntStat);
853                 if ( ui32IntStat &
854                         ~AM_HAL_TIMER_MASK(AM_HAL_WRITE_WAIT_TIMER, AM_HAL_TIMER_COMPARE_BOTH) )
855                 {
856                     NVIC_SetPendingIRQ(TIMER_IRQn);
857                 }
858             }
859 
860             //
861             // Restore interrupts
862             //
863             __set_BASEPRI(origBasePri);
864         }
865     }
866 
867     //
868     // End critical section
869     //
870     AM_CRITICAL_END
871 
872     return ui32Status;
873 
874 } // am_hal_util_write_and_wait()
875 #endif // defined(AM_HAL_PWRCTL_HPLP_WA)
876 
877 // ****************************************************************************
878 //
879 //  am_hal_pwrctrl_mcu_mode_status()
880 //
881 // ****************************************************************************
882 uint32_t
am_hal_pwrctrl_mcu_mode_status(am_hal_pwrctrl_mcu_mode_e * peCurrentPowerMode)883 am_hal_pwrctrl_mcu_mode_status(am_hal_pwrctrl_mcu_mode_e *peCurrentPowerMode)
884 {
885 #ifndef AM_HAL_DISABLE_API_VALIDATION
886     if ( peCurrentPowerMode == 0 )
887     {
888         return AM_HAL_STATUS_INVALID_ARG;
889     }
890 #endif // AM_HAL_DISABLE_API_VALIDATION
891 
892     *peCurrentPowerMode = g_eCurrPwrMode;
893     return AM_HAL_STATUS_SUCCESS;
894 
895 } // am_hal_pwrctrl_mcu_mode_status()
896 
897 // ****************************************************************************
898 //
899 //  am_hal_pwrctrl_mcu_mode_select()
900 //  Select the MCU power mode.
901 //
902 // ****************************************************************************
903 uint32_t
am_hal_pwrctrl_mcu_mode_select(am_hal_pwrctrl_mcu_mode_e ePowerMode)904 am_hal_pwrctrl_mcu_mode_select(am_hal_pwrctrl_mcu_mode_e ePowerMode)
905 {
906     uint32_t ui32Status;
907 
908 #ifndef AM_HAL_DISABLE_API_VALIDATION
909     if ( (ePowerMode != AM_HAL_PWRCTRL_MCU_MODE_LOW_POWER)      &&
910          (ePowerMode != AM_HAL_PWRCTRL_MCU_MODE_HIGH_PERFORMANCE) )
911     {
912         return AM_HAL_STATUS_INVALID_ARG;
913     }
914 
915     //
916     // We must be using SIMOBUCK in order to go to HP mode.
917     //
918     if ( (ePowerMode == AM_HAL_PWRCTRL_MCU_MODE_HIGH_PERFORMANCE)   &&
919          (PWRCTRL->VRSTATUS_b.SIMOBUCKST != PWRCTRL_VRSTATUS_SIMOBUCKST_ACT) )
920     {
921         return AM_HAL_STATUS_INVALID_OPERATION;
922     }
923 #endif // AM_HAL_DISABLE_API_VALIDATION
924 
925     if ( ePowerMode == g_eCurrPwrMode )
926     {
927         return AM_HAL_STATUS_SUCCESS;
928     }
929 
930     g_eCurrPwrMode = ePowerMode;
931 
932     //
933     // Set the MCU power mode.
934     //
935 #ifdef AM_HAL_PWRCTL_HPLP_WA
936     ui32Status = am_hal_util_write_and_wait((uint32_t*)&PWRCTRL->MCUPERFREQ,
937                                             0xFFFFFFFF, (uint32_t)ePowerMode,
938                                             AM_HAL_PWRCTL_HPLP_DELAY);
939     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
940     {
941         //
942         // This means that there is another interrupt with the highest
943         // priority and the AM_HAL_PWRCTL_HPLP_WA will not work.
944         //
945         return ui32Status;
946     }
947 #else
948     PWRCTRL->MCUPERFREQ_b.MCUPERFREQ = ePowerMode;
949 #endif // AM_HAL_PWRCTL_HPLP_WA
950 
951     //
952     // Wait for the ACK
953     //
954     ui32Status = AM_HAL_STATUS_TIMEOUT;
955     for ( uint32_t i = 0; i < 5; i++ )
956     {
957         if ( PWRCTRL->MCUPERFREQ_b.MCUPERFACK > 0 )
958         {
959             ui32Status = AM_HAL_STATUS_SUCCESS;
960             break;
961         }
962         am_hal_delay_us(1);
963     }
964 
965     //
966     // Check for timeout.
967     //
968     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
969     {
970         //
971         // Caution: Reaching this point means the device is in an unpredictable
972         //          state and may not be able to recover.
973         //
974         return ui32Status;
975     }
976 
977     //
978     // Check the MCU power mode status and return SUCCESS/FAIL.
979     //
980     if ( PWRCTRL->MCUPERFREQ_b.MCUPERFSTATUS == ePowerMode )
981     {
982         return AM_HAL_STATUS_SUCCESS;
983     }
984     else
985     {
986         //
987         // Caution: Reaching this point means the device is in an unpredictable
988         //          state and may not be able to recover.
989         //
990         return AM_HAL_STATUS_FAIL;
991     }
992 
993 } // am_hal_pwrctrl_mcu_mode_select()
994 
995 // ****************************************************************************
996 //
997 //  am_hal_pwrctrl_mcu_memory_config()
998 //  Configure the MCU memory.
999 //
1000 // ****************************************************************************
1001 uint32_t
am_hal_pwrctrl_mcu_memory_config(am_hal_pwrctrl_mcu_memory_config_t * psConfig)1002 am_hal_pwrctrl_mcu_memory_config(am_hal_pwrctrl_mcu_memory_config_t *psConfig)
1003 {
1004     uint32_t      ui32Status;
1005 
1006     //
1007     // Configure the MCU Cache.
1008     //
1009     switch ( psConfig->eCacheCfg )
1010     {
1011         case AM_HAL_PWRCTRL_CACHE_NONE:
1012             PWRCTRL->MEMPWREN_b.PWRENCACHEB0 = PWRCTRL_MEMPWREN_PWRENCACHEB0_DIS;
1013             PWRCTRL->MEMPWREN_b.PWRENCACHEB2 = PWRCTRL_MEMPWREN_PWRENCACHEB2_DIS;
1014             break;
1015         case AM_HAL_PWRCTRL_CACHEB0_ONLY:
1016             PWRCTRL->MEMPWREN_b.PWRENCACHEB0 = PWRCTRL_MEMPWREN_PWRENCACHEB0_EN;
1017             PWRCTRL->MEMPWREN_b.PWRENCACHEB2 = PWRCTRL_MEMPWREN_PWRENCACHEB2_DIS;
1018             break;
1019         case AM_HAL_PWRCTRL_CACHE_ALL:
1020             PWRCTRL->MEMPWREN_b.PWRENCACHEB0 = PWRCTRL_MEMPWREN_PWRENCACHEB0_EN;
1021             PWRCTRL->MEMPWREN_b.PWRENCACHEB2 = PWRCTRL_MEMPWREN_PWRENCACHEB2_EN;
1022             break;
1023     }
1024 
1025     //
1026     // Configure the MCU Tightly Coupled Memory.
1027     //
1028     PWRCTRL->MEMPWREN_b.PWRENDTCM = psConfig->eDTCMCfg;
1029 
1030     //
1031     // Configure the Non-Volatile Memory.
1032     //
1033     PWRCTRL->MEMPWREN_b.PWRENNVM0 = psConfig->bEnableNVM0;
1034 
1035     DIAG_SUPPRESS_VOLATILE_ORDER()
1036     //
1037     // Wait for Status
1038     //
1039     ui32Status = am_hal_delay_us_status_check(AM_HAL_PWRCTRL_MAX_WAIT_US,
1040                                               (uint32_t)&PWRCTRL->MEMPWRSTATUS,
1041                                               AM_HAL_PWRCTRL_MEMPWREN_MASK,
1042                                               PWRCTRL->MEMPWREN,
1043                                               true);
1044 
1045     //
1046     // Check for timeout.
1047     //
1048     if (AM_HAL_STATUS_SUCCESS != ui32Status)
1049     {
1050         return ui32Status;
1051     }
1052 
1053     //
1054     // Check the MCU power mode status and return SUCCESS/FAIL.
1055     //
1056     if ((PWRCTRL->MEMPWRSTATUS_b.PWRSTCACHEB0 != PWRCTRL->MEMPWREN_b.PWRENCACHEB0)  ||
1057         (PWRCTRL->MEMPWRSTATUS_b.PWRSTCACHEB2 != PWRCTRL->MEMPWREN_b.PWRENCACHEB2)  ||
1058         (PWRCTRL->MEMPWRSTATUS_b.PWRSTDTCM != PWRCTRL->MEMPWREN_b.PWRENDTCM)        ||
1059         (PWRCTRL->MEMPWRSTATUS_b.PWRSTNVM0 != PWRCTRL->MEMPWREN_b.PWRENNVM0))
1060     {
1061         return AM_HAL_STATUS_FAIL;
1062     }
1063 
1064     DIAG_DEFAULT_VOLATILE_ORDER()
1065 
1066     //
1067     // Configure Cache retention.
1068     //
1069     if (psConfig->bRetainCache)
1070     {
1071         PWRCTRL->MEMRETCFG_b.CACHEPWDSLP = PWRCTRL_MEMRETCFG_CACHEPWDSLP_DIS;
1072     }
1073     else
1074     {
1075         PWRCTRL->MEMRETCFG_b.CACHEPWDSLP = PWRCTRL_MEMRETCFG_CACHEPWDSLP_EN;
1076     }
1077 
1078     //
1079     // Configure the Non-Volatile Memory retention.
1080     //
1081     if (psConfig->bRetainNVM0)
1082     {
1083         PWRCTRL->MEMRETCFG_b.NVM0PWDSLP = PWRCTRL_MEMRETCFG_NVM0PWDSLP_DIS;
1084     }
1085     else
1086     {
1087         PWRCTRL->MEMRETCFG_b.NVM0PWDSLP = PWRCTRL_MEMRETCFG_NVM0PWDSLP_EN;
1088     }
1089 
1090     //
1091     // Configure the MCU Tightly Coupled Memory retention.
1092     //
1093     switch ( psConfig->eRetainDTCM )
1094     {
1095         case AM_HAL_PWRCTRL_DTCM_NONE:
1096             PWRCTRL->MEMRETCFG_b.DTCMPWDSLP = PWRCTRL_MEMRETCFG_DTCMPWDSLP_ALL;
1097             break;
1098         case AM_HAL_PWRCTRL_DTCM_8K:
1099             PWRCTRL->MEMRETCFG_b.DTCMPWDSLP = PWRCTRL_MEMRETCFG_DTCMPWDSLP_ALLBUTGROUP0DTCM0;
1100             break;
1101         case AM_HAL_PWRCTRL_DTCM_128K:
1102             PWRCTRL->MEMRETCFG_b.DTCMPWDSLP = PWRCTRL_MEMRETCFG_DTCMPWDSLP_GROUP1;
1103             break;
1104         case AM_HAL_PWRCTRL_DTCM_384K:
1105             PWRCTRL->MEMRETCFG_b.DTCMPWDSLP = PWRCTRL_MEMRETCFG_DTCMPWDSLP_NONE;
1106             break;
1107     }
1108 
1109     return AM_HAL_STATUS_SUCCESS;
1110 
1111 } // am_hal_pwrctrl_mcu_memory_config()
1112 
1113 // ****************************************************************************
1114 //
1115 //  am_hal_pwrctrl_mcu_memory_config_get()
1116 //  Get the MCU Memory configuration.
1117 //
1118 // ****************************************************************************
1119 uint32_t
am_hal_pwrctrl_mcu_memory_config_get(am_hal_pwrctrl_mcu_memory_config_t * psConfig)1120 am_hal_pwrctrl_mcu_memory_config_get(am_hal_pwrctrl_mcu_memory_config_t *psConfig)
1121 {
1122     //
1123     // Get the MCU Cache configuration.
1124     //
1125     if (PWRCTRL->MEMPWREN_b.PWRENCACHEB0 == PWRCTRL_MEMPWREN_PWRENCACHEB0_EN)
1126     {
1127         if (PWRCTRL->MEMPWREN_b.PWRENCACHEB2 == PWRCTRL_MEMPWREN_PWRENCACHEB2_EN)
1128         {
1129             psConfig->eCacheCfg = AM_HAL_PWRCTRL_CACHE_ALL;
1130         }
1131         else
1132         {
1133             psConfig->eCacheCfg = AM_HAL_PWRCTRL_CACHEB0_ONLY;
1134         }
1135     }
1136     else
1137     {
1138         if (PWRCTRL->MEMPWREN_b.PWRENCACHEB2 == PWRCTRL_MEMPWREN_PWRENCACHEB2_EN)
1139         {
1140             return AM_HAL_STATUS_FAIL;  // Not allowed to select Cache B2 only.
1141             // This should never be possible.
1142         }
1143         else
1144         {
1145             psConfig->eCacheCfg = AM_HAL_PWRCTRL_CACHE_NONE;
1146         }
1147     }
1148 
1149     //
1150     // Get the MCU Tightly Coupled Memory configuration.
1151     //
1152     psConfig->eDTCMCfg =
1153         (am_hal_pwrctrl_dtcm_select_e)PWRCTRL->MEMPWREN_b.PWRENDTCM;
1154 
1155     //
1156     // Get the Non-Volatile Memory configuration.
1157     //
1158     psConfig->bEnableNVM0 = PWRCTRL->MEMPWREN_b.PWRENNVM0;
1159 
1160     //
1161     // Get the Cache retention configuration.
1162     //
1163     psConfig->bRetainCache =
1164         (PWRCTRL->MEMRETCFG_b.CACHEPWDSLP == PWRCTRL_MEMRETCFG_CACHEPWDSLP_DIS);
1165 
1166     //
1167     // Configure the Non-Volatile Memory retention.
1168     //
1169     psConfig->bRetainNVM0 =
1170         (PWRCTRL->MEMRETCFG_b.NVM0PWDSLP == PWRCTRL_MEMRETCFG_NVM0PWDSLP_DIS);
1171 
1172     //
1173     // Configure the MCU Tightly Coupled Memory retention.
1174     //
1175     if (PWRCTRL->MEMRETCFG_b.DTCMPWDSLP == PWRCTRL_MEMRETCFG_DTCMPWDSLP_ALL)
1176     {
1177         psConfig->eRetainDTCM = AM_HAL_PWRCTRL_DTCM_NONE;
1178     }
1179     else if (PWRCTRL->MEMRETCFG_b.DTCMPWDSLP == PWRCTRL_MEMRETCFG_DTCMPWDSLP_ALLBUTGROUP0DTCM0)
1180     {
1181         psConfig->eRetainDTCM = AM_HAL_PWRCTRL_DTCM_8K;
1182     }
1183     else if (PWRCTRL->MEMRETCFG_b.DTCMPWDSLP == PWRCTRL_MEMRETCFG_DTCMPWDSLP_GROUP1)
1184     {
1185         psConfig->eRetainDTCM = AM_HAL_PWRCTRL_DTCM_128K;
1186     }
1187     else if (PWRCTRL->MEMRETCFG_b.DTCMPWDSLP == PWRCTRL_MEMRETCFG_DTCMPWDSLP_NONE)
1188     {
1189         psConfig->eRetainDTCM = AM_HAL_PWRCTRL_DTCM_384K;
1190     }
1191     else
1192     {
1193         return AM_HAL_STATUS_OUT_OF_RANGE;
1194     }
1195 
1196     return AM_HAL_STATUS_SUCCESS;
1197 } // am_hal_pwrctrl_mcu_memory_config_get()
1198 
1199 // ****************************************************************************
1200 //
1201 //  am_hal_pwrctrl_sram_config()
1202 //  Configure the Shared RAM.
1203 //
1204 // ****************************************************************************
1205 uint32_t
am_hal_pwrctrl_sram_config(am_hal_pwrctrl_sram_memcfg_t * psConfig)1206 am_hal_pwrctrl_sram_config(am_hal_pwrctrl_sram_memcfg_t *psConfig)
1207 {
1208     uint32_t      ui32Status;
1209 
1210     //
1211     // Configure the Shared RAM.
1212     //
1213     PWRCTRL->SSRAMPWREN_b.PWRENSSRAM = psConfig->eSRAMCfg;
1214 
1215     DIAG_SUPPRESS_VOLATILE_ORDER()
1216 
1217     //
1218     // Wait for Status
1219     //
1220     ui32Status = am_hal_delay_us_status_check(AM_HAL_PWRCTRL_MAX_WAIT_US,
1221                                               (uint32_t)&PWRCTRL->SSRAMPWRST,
1222                                               PWRCTRL_SSRAMPWRST_SSRAMPWRST_Msk,
1223                                               PWRCTRL->SSRAMPWREN,
1224                                               true);
1225 
1226     //
1227     // Check for error.
1228     //
1229     if (AM_HAL_STATUS_SUCCESS != ui32Status)
1230     {
1231         return ui32Status;
1232     }
1233 
1234     //
1235     // Check the Shared RAM power mode status.
1236     //
1237     if (PWRCTRL->SSRAMPWRST_b.SSRAMPWRST != PWRCTRL->SSRAMPWREN_b.PWRENSSRAM)
1238     {
1239         return AM_HAL_STATUS_FAIL;
1240     }
1241     DIAG_DEFAULT_VOLATILE_ORDER()
1242 
1243     //
1244     // Configure the Shared RAM domain active based on the states of the MCU,
1245     // graphics, and display.
1246     //
1247     PWRCTRL->SSRAMRETCFG_b.SSRAMACTMCU  = psConfig->eActiveWithMCU;
1248     PWRCTRL->SSRAMRETCFG_b.SSRAMACTGFX  = psConfig->eActiveWithGFX;
1249     PWRCTRL->SSRAMRETCFG_b.SSRAMACTDISP = psConfig->eActiveWithDISP;
1250     PWRCTRL->SSRAMRETCFG_b.SSRAMACTDSP  = psConfig->eActiveWithDSP;
1251 
1252     //
1253     // Configure the Shared RAM retention.
1254     //
1255     switch ( psConfig->eSRAMRetain )
1256     {
1257         case AM_HAL_PWRCTRL_SRAM_NONE:
1258             PWRCTRL->SSRAMRETCFG_b.SSRAMPWDSLP = PWRCTRL_SSRAMRETCFG_SSRAMPWDSLP_ALL;
1259             break;
1260         case AM_HAL_PWRCTRL_SRAM_1M_GRP0:   // Retain lower 1M, pwr dwn upper 1M
1261             PWRCTRL->SSRAMRETCFG_b.SSRAMPWDSLP = PWRCTRL_SSRAMRETCFG_SSRAMPWDSLP_GROUP1;
1262             break;
1263         case AM_HAL_PWRCTRL_SRAM_1M_GRP1:   // Retain upper 1M, pwr dwn lower 1M
1264             PWRCTRL->SSRAMRETCFG_b.SSRAMPWDSLP = PWRCTRL_SSRAMRETCFG_SSRAMPWDSLP_GROUP0;
1265             break;
1266         case AM_HAL_PWRCTRL_SRAM_ALL:       // Retain all SSRAM, pwr dwn none
1267             PWRCTRL->SSRAMRETCFG_b.SSRAMPWDSLP = PWRCTRL_SSRAMRETCFG_SSRAMPWDSLP_NONE;
1268             break;
1269     }
1270 
1271     return AM_HAL_STATUS_SUCCESS;
1272 } // am_hal_pwrctrl_sram_config()
1273 
1274 // ****************************************************************************
1275 //
1276 //  am_hal_pwrctrl_sram_config_get()
1277 //  Get the current Shared RAM configuration.
1278 //
1279 // ****************************************************************************
1280 uint32_t
am_hal_pwrctrl_sram_config_get(am_hal_pwrctrl_sram_memcfg_t * psConfig)1281 am_hal_pwrctrl_sram_config_get(am_hal_pwrctrl_sram_memcfg_t *psConfig)
1282 {
1283     //
1284     // Get the Shared RAM configuration.
1285     //
1286     psConfig->eSRAMCfg = (am_hal_pwrctrl_sram_select_e)PWRCTRL->SSRAMPWREN_b.PWRENSSRAM;
1287 
1288     //
1289     // Get the SRAM active configurations based for each of MCU, graphics, and display.
1290     //
1291     psConfig->eActiveWithMCU  = (am_hal_pwrctrl_sram_select_e)PWRCTRL->SSRAMRETCFG_b.SSRAMACTMCU;
1292     psConfig->eActiveWithGFX  = (am_hal_pwrctrl_sram_select_e)PWRCTRL->SSRAMRETCFG_b.SSRAMACTGFX;
1293     psConfig->eActiveWithDISP = (am_hal_pwrctrl_sram_select_e)PWRCTRL->SSRAMRETCFG_b.SSRAMACTDISP;
1294     psConfig->eActiveWithDSP  = (am_hal_pwrctrl_sram_select_e)PWRCTRL->SSRAMRETCFG_b.SSRAMACTDSP;
1295 
1296     //
1297     // Get the SRAM retention configuration.
1298     //
1299     if (PWRCTRL->SSRAMRETCFG_b.SSRAMPWDSLP == PWRCTRL_SSRAMRETCFG_SSRAMPWDSLP_ALL)
1300     {
1301         psConfig->eSRAMRetain = AM_HAL_PWRCTRL_SRAM_NONE;
1302     }
1303     else if (PWRCTRL->SSRAMRETCFG_b.SSRAMPWDSLP == PWRCTRL_SSRAMRETCFG_SSRAMPWDSLP_NONE)
1304     {
1305         psConfig->eSRAMRetain = AM_HAL_PWRCTRL_SRAM_ALL;
1306     }
1307     else if (PWRCTRL->SSRAMRETCFG_b.SSRAMPWDSLP == PWRCTRL_SSRAMRETCFG_SSRAMPWDSLP_GROUP0)
1308     {
1309         psConfig->eSRAMRetain = AM_HAL_PWRCTRL_SRAM_1M_GRP1;
1310     }
1311     else if (PWRCTRL->SSRAMRETCFG_b.SSRAMPWDSLP == PWRCTRL_SSRAMRETCFG_SSRAMPWDSLP_GROUP1)
1312     {
1313         psConfig->eSRAMRetain = AM_HAL_PWRCTRL_SRAM_1M_GRP0;
1314     }
1315     else
1316     {
1317         return AM_HAL_STATUS_OUT_OF_RANGE;
1318     }
1319 
1320     return AM_HAL_STATUS_SUCCESS;
1321 } // am_hal_pwrctrl_sram_config_get()
1322 
1323 // ****************************************************************************
1324 //
1325 //  am_hal_pwrctrl_dsp_mode_select()
1326 //  Select the DSP power mode.
1327 //
1328 // ****************************************************************************
1329 uint32_t
am_hal_pwrctrl_dsp_mode_select(am_hal_dsp_select_e eDSP,am_hal_pwrctrl_dsp_mode_e ePowerMode)1330 am_hal_pwrctrl_dsp_mode_select(am_hal_dsp_select_e eDSP,
1331                                am_hal_pwrctrl_dsp_mode_e ePowerMode)
1332 {
1333     uint32_t      ui32Status = AM_HAL_STATUS_SUCCESS;
1334 
1335     //
1336     // Set the DSP power mode.
1337     //
1338     switch ( eDSP )
1339     {
1340         case AM_HAL_DSP0:
1341             PWRCTRL->DSP0PERFREQ_b.DSP0PERFREQ = ePowerMode;
1342             break;
1343         case AM_HAL_DSP1:
1344             PWRCTRL->DSP1PERFREQ_b.DSP1PERFREQ = ePowerMode;
1345             break;
1346     }
1347 
1348     //
1349     // Wait for ACK
1350     //
1351     switch ( eDSP )
1352     {
1353         case AM_HAL_DSP0:
1354             ui32Status = am_hal_delay_us_status_check(AM_HAL_PWRCTRL_MAX_WAIT_US,
1355                                                       (uint32_t)&PWRCTRL->DSP0PERFREQ,
1356                                                       PWRCTRL_DSP0PERFREQ_DSP0PERFACK_Msk,
1357                                                       (1 << PWRCTRL_DSP0PERFREQ_DSP0PERFACK_Pos),
1358                                                       true);
1359         break;
1360     case AM_HAL_DSP1:
1361         ui32Status = am_hal_delay_us_status_check(AM_HAL_PWRCTRL_MAX_WAIT_US,
1362                                                   (uint32_t)&PWRCTRL->DSP1PERFREQ,
1363                                                   PWRCTRL_DSP1PERFREQ_DSP1PERFACK_Msk,
1364                                                   (1 << PWRCTRL_DSP1PERFREQ_DSP1PERFACK_Pos),
1365                                                   true);
1366         break;
1367     }
1368 
1369     //
1370     // Check for timeout.
1371     //
1372     if (AM_HAL_STATUS_SUCCESS != ui32Status)
1373     {
1374         return ui32Status;
1375     }
1376 
1377     //
1378     // Check the DSP power mode status and return SUCCESS/FAIL.
1379     //
1380     switch ( eDSP )
1381     {
1382         case AM_HAL_DSP0:
1383             if (ePowerMode != PWRCTRL->DSP0PERFREQ_b.DSP0PERFSTATUS)
1384             {
1385                 return AM_HAL_STATUS_FAIL;
1386             }
1387             break;
1388         case AM_HAL_DSP1:
1389             if (ePowerMode != PWRCTRL->DSP1PERFREQ_b.DSP1PERFSTATUS)
1390             {
1391                 return AM_HAL_STATUS_FAIL;
1392             }
1393             break;
1394     }
1395 
1396     return AM_HAL_STATUS_SUCCESS;
1397 
1398 } // am_hal_pwrctrl_dsp_mode_select()
1399 
1400 // ****************************************************************************
1401 //
1402 //  dsp0_memory_config()
1403 //
1404 // ****************************************************************************
1405 static uint32_t
dsp0_memory_config(am_hal_pwrctrl_dsp_memory_config_t * psConfig)1406 dsp0_memory_config(am_hal_pwrctrl_dsp_memory_config_t *psConfig)
1407 {
1408     uint32_t      ui32Status;
1409 
1410     // Configure ICache.
1411     if (psConfig->bEnableICache)
1412     {
1413         PWRCTRL->DSP0MEMPWREN_b.PWRENDSP0ICACHE = PWRCTRL_DSP0MEMPWREN_PWRENDSP0ICACHE_ON;
1414     }
1415     else
1416     {
1417         PWRCTRL->DSP0MEMPWREN_b.PWRENDSP0ICACHE = PWRCTRL_DSP0MEMPWREN_PWRENDSP0ICACHE_OFF;
1418     }
1419 
1420     // Configure RAM.
1421     if (psConfig->bEnableRAM)
1422     {
1423         PWRCTRL->DSP0MEMPWREN_b.PWRENDSP0RAM = PWRCTRL_DSP0MEMPWREN_PWRENDSP0RAM_ON;
1424     }
1425     else
1426     {
1427         PWRCTRL->DSP0MEMPWREN_b.PWRENDSP0RAM = PWRCTRL_DSP0MEMPWREN_PWRENDSP0RAM_OFF;
1428     }
1429 
1430     DIAG_SUPPRESS_VOLATILE_ORDER()
1431 
1432     //
1433     // Wait for Status
1434     //
1435     ui32Status = am_hal_delay_us_status_check(AM_HAL_PWRCTRL_MAX_WAIT_US,
1436                                               (uint32_t)&PWRCTRL->DSP0MEMPWRST,
1437                                               AM_HAL_PWRCTRL_DSPMEMPWRST_MASK,
1438                                               PWRCTRL->DSP0MEMPWREN,
1439                                               true);
1440 
1441     //
1442     // Check for error.
1443     //
1444     if (AM_HAL_STATUS_SUCCESS != ui32Status)
1445     {
1446         return ui32Status;
1447     }
1448 
1449     //
1450     // Check for timeout.
1451     //
1452     if ((PWRCTRL->DSP0MEMPWRST_b.PWRSTDSP0ICACHE != PWRCTRL->DSP0MEMPWREN_b.PWRENDSP0ICACHE) ||
1453         (PWRCTRL->DSP0MEMPWRST_b.PWRSTDSP0RAM != PWRCTRL->DSP0MEMPWREN_b.PWRENDSP0RAM) )
1454     {
1455         return AM_HAL_STATUS_FAIL;
1456     }
1457     DIAG_DEFAULT_VOLATILE_ORDER()
1458 
1459     // Configure ICache Retention.
1460     if (psConfig->bRetainCache)
1461     {
1462         PWRCTRL->DSP0MEMRETCFG_b.ICACHEPWDDSP0OFF = PWRCTRL_DSP0MEMRETCFG_ICACHEPWDDSP0OFF_RET;
1463     }
1464     else
1465     {
1466         PWRCTRL->DSP0MEMRETCFG_b.ICACHEPWDDSP0OFF = PWRCTRL_DSP0MEMRETCFG_ICACHEPWDDSP0OFF_PWD;
1467     }
1468 
1469     // Configure IRAM Retention.
1470     if (psConfig->bActiveRAM)
1471     {
1472         PWRCTRL->DSP0MEMRETCFG_b.DSP0RAMACTMCU = PWRCTRL_DSP0MEMRETCFG_DSP0RAMACTMCU_ACT;
1473     }
1474     else
1475     {
1476         PWRCTRL->DSP0MEMRETCFG_b.DSP0RAMACTMCU = PWRCTRL_DSP0MEMRETCFG_DSP0RAMACTMCU_WAKEONDEMAND;
1477     }
1478     if (psConfig->bRetainRAM)
1479     {
1480         PWRCTRL->DSP0MEMRETCFG_b.RAMPWDDSP0OFF = PWRCTRL_DSP0MEMRETCFG_RAMPWDDSP0OFF_RET;
1481     }
1482     else
1483     {
1484         PWRCTRL->DSP0MEMRETCFG_b.RAMPWDDSP0OFF = PWRCTRL_DSP0MEMRETCFG_RAMPWDDSP0OFF_PWD;
1485     }
1486 
1487     return AM_HAL_STATUS_SUCCESS;
1488 } // dsp0_memory_config()
1489 
1490 // ****************************************************************************
1491 //
1492 //  dsp1_memory_config()
1493 //
1494 // ****************************************************************************
1495 static uint32_t
dsp1_memory_config(am_hal_pwrctrl_dsp_memory_config_t * psConfig)1496 dsp1_memory_config(am_hal_pwrctrl_dsp_memory_config_t *psConfig)
1497 {
1498     uint32_t      ui32Status;
1499 
1500     // Configure ICache.
1501     if (psConfig->bEnableICache)
1502     {
1503         PWRCTRL->DSP1MEMPWREN_b.PWRENDSP1ICACHE = PWRCTRL_DSP1MEMPWREN_PWRENDSP1ICACHE_ON;
1504     }
1505     else
1506     {
1507         PWRCTRL->DSP1MEMPWREN_b.PWRENDSP1ICACHE = PWRCTRL_DSP1MEMPWREN_PWRENDSP1ICACHE_OFF;
1508     }
1509 
1510     // Configure RAM.
1511     if (psConfig->bEnableRAM)
1512     {
1513         PWRCTRL->DSP1MEMPWREN_b.PWRENDSP1RAM = PWRCTRL_DSP1MEMPWREN_PWRENDSP1RAM_ON;
1514     }
1515     else
1516     {
1517         PWRCTRL->DSP1MEMPWREN_b.PWRENDSP1RAM = PWRCTRL_DSP1MEMPWREN_PWRENDSP1RAM_OFF;
1518     }
1519 
1520     DIAG_SUPPRESS_VOLATILE_ORDER()
1521 
1522     //
1523     // Wait for Status
1524     //
1525     ui32Status = am_hal_delay_us_status_check(AM_HAL_PWRCTRL_MAX_WAIT_US,
1526                                               (uint32_t)&PWRCTRL->DSP1MEMPWRST,
1527                                               AM_HAL_PWRCTRL_DSPMEMPWRST_MASK,
1528                                               PWRCTRL->DSP1MEMPWREN,
1529                                               true);
1530 
1531     //
1532     // Check for error.
1533     //
1534     if (AM_HAL_STATUS_SUCCESS != ui32Status)
1535     {
1536         return ui32Status;
1537     }
1538 
1539     //
1540     // Check for timeout.
1541     //
1542     if ((PWRCTRL->DSP1MEMPWRST_b.PWRSTDSP1ICACHE != PWRCTRL->DSP1MEMPWREN_b.PWRENDSP1ICACHE) ||
1543         (PWRCTRL->DSP1MEMPWRST_b.PWRSTDSP1RAM != PWRCTRL->DSP1MEMPWREN_b.PWRENDSP1RAM) )
1544     {
1545         return AM_HAL_STATUS_FAIL;
1546     }
1547     DIAG_DEFAULT_VOLATILE_ORDER()
1548 
1549     // Configure ICache Retention.
1550     if (psConfig->bRetainCache)
1551     {
1552         PWRCTRL->DSP1MEMRETCFG_b.ICACHEPWDDSP1OFF = PWRCTRL_DSP1MEMRETCFG_ICACHEPWDDSP1OFF_RET;
1553     }
1554     else
1555     {
1556         PWRCTRL->DSP1MEMRETCFG_b.ICACHEPWDDSP1OFF = PWRCTRL_DSP1MEMRETCFG_ICACHEPWDDSP1OFF_PWD;
1557     }
1558 
1559     // Configure IRAM Retention.
1560     if (psConfig->bActiveRAM)
1561     {
1562         PWRCTRL->DSP1MEMRETCFG_b.DSP1RAMACTMCU = PWRCTRL_DSP1MEMRETCFG_DSP1RAMACTMCU_ACT;
1563     }
1564     else
1565     {
1566         PWRCTRL->DSP1MEMRETCFG_b.DSP1RAMACTMCU = PWRCTRL_DSP1MEMRETCFG_DSP1RAMACTMCU_WAKEONDEMAND;
1567     }
1568     if (psConfig->bRetainRAM)
1569     {
1570         PWRCTRL->DSP1MEMRETCFG_b.RAMPWDDSP1OFF = PWRCTRL_DSP1MEMRETCFG_RAMPWDDSP1OFF_RET;
1571     }
1572     else
1573     {
1574         PWRCTRL->DSP1MEMRETCFG_b.RAMPWDDSP1OFF = PWRCTRL_DSP1MEMRETCFG_RAMPWDDSP1OFF_PWD;
1575     }
1576 
1577     return AM_HAL_STATUS_SUCCESS;
1578 } // dsp1_memory_config()
1579 
1580 // ****************************************************************************
1581 //
1582 //  am_hal_pwrctrl_dsp_memory_config()
1583 //  Configure the DSP memory.
1584 //
1585 // ****************************************************************************
1586 uint32_t
am_hal_pwrctrl_dsp_memory_config(am_hal_dsp_select_e eDSP,am_hal_pwrctrl_dsp_memory_config_t * psConfig)1587 am_hal_pwrctrl_dsp_memory_config(am_hal_dsp_select_e eDSP,
1588                                  am_hal_pwrctrl_dsp_memory_config_t *psConfig)
1589 {
1590     uint32_t    retval = AM_HAL_STATUS_SUCCESS;
1591 
1592     switch ( eDSP )
1593     {
1594         case AM_HAL_DSP0:
1595             retval = dsp0_memory_config(psConfig);
1596             break;
1597         case AM_HAL_DSP1:
1598             retval = dsp1_memory_config(psConfig);
1599             break;
1600     }
1601 
1602     return retval;
1603 } // am_hal_pwrctrl_dsp_memory_config()
1604 
1605 // ****************************************************************************
1606 //
1607 //  dsp0_memory_get()
1608 //
1609 // ****************************************************************************
1610 static uint32_t
dsp0_memory_get(am_hal_pwrctrl_dsp_memory_config_t * psConfig)1611 dsp0_memory_get(am_hal_pwrctrl_dsp_memory_config_t *psConfig)
1612 {
1613 
1614     // Read the ICache configuration.
1615     psConfig->bEnableICache = (PWRCTRL_DSP0MEMPWREN_PWRENDSP0ICACHE_ON == PWRCTRL->DSP0MEMPWREN_b.PWRENDSP0ICACHE );
1616     psConfig->bRetainCache  = (PWRCTRL_DSP0MEMRETCFG_ICACHEPWDDSP0OFF_RET == PWRCTRL->DSP0MEMRETCFG_b.ICACHEPWDDSP0OFF);
1617 
1618     // Read the RAM configuration.
1619     psConfig->bEnableRAM    = (PWRCTRL->DSP0MEMPWREN_b.PWRENDSP0RAM == PWRCTRL_DSP0MEMPWREN_PWRENDSP0RAM_ON);
1620     psConfig->bActiveRAM    = (PWRCTRL->DSP0MEMRETCFG_b.DSP0RAMACTMCU == PWRCTRL_DSP0MEMRETCFG_DSP0RAMACTMCU_ACT);
1621     psConfig->bRetainRAM    = (PWRCTRL->DSP0MEMRETCFG_b.RAMPWDDSP0OFF == PWRCTRL_DSP0MEMRETCFG_RAMPWDDSP0OFF_RET);
1622 
1623     return AM_HAL_STATUS_SUCCESS;
1624 } // dsp0_memory_get()
1625 
1626 // ****************************************************************************
1627 //
1628 //  dsp1_memory_get()
1629 //
1630 // ****************************************************************************
1631 static uint32_t
dsp1_memory_get(am_hal_pwrctrl_dsp_memory_config_t * psConfig)1632 dsp1_memory_get(am_hal_pwrctrl_dsp_memory_config_t *psConfig)
1633 {
1634     // Read the ICache configuration.
1635     psConfig->bEnableICache = (PWRCTRL_DSP1MEMPWREN_PWRENDSP1ICACHE_ON == PWRCTRL->DSP1MEMPWREN_b.PWRENDSP1ICACHE );
1636     psConfig->bRetainCache  = (PWRCTRL_DSP1MEMRETCFG_ICACHEPWDDSP1OFF_RET == PWRCTRL->DSP1MEMRETCFG_b.ICACHEPWDDSP1OFF);
1637 
1638     // Read the RAM configuration.
1639     psConfig->bEnableRAM    = (PWRCTRL->DSP1MEMPWREN_b.PWRENDSP1RAM == PWRCTRL_DSP1MEMPWREN_PWRENDSP1RAM_ON);
1640     psConfig->bActiveRAM    = (PWRCTRL->DSP1MEMRETCFG_b.DSP1RAMACTMCU == PWRCTRL_DSP1MEMRETCFG_DSP1RAMACTMCU_ACT);
1641     psConfig->bRetainRAM    = (PWRCTRL->DSP1MEMRETCFG_b.RAMPWDDSP1OFF == PWRCTRL_DSP1MEMRETCFG_RAMPWDDSP1OFF_RET);
1642 
1643     return AM_HAL_STATUS_SUCCESS;
1644 } // dsp1_memory_get()
1645 
1646 // ****************************************************************************
1647 //
1648 //  am_hal_pwrctrl_dsp_memory_config_get()
1649 //  Get the current the DSP memory configuration.
1650 //
1651 // ****************************************************************************
1652 uint32_t
am_hal_pwrctrl_dsp_memory_config_get(am_hal_dsp_select_e eDSP,am_hal_pwrctrl_dsp_memory_config_t * psConfig)1653 am_hal_pwrctrl_dsp_memory_config_get(am_hal_dsp_select_e eDSP,
1654                                      am_hal_pwrctrl_dsp_memory_config_t *psConfig)
1655 {
1656     uint32_t      retval = AM_HAL_STATUS_SUCCESS;
1657 
1658     switch ( eDSP )
1659     {
1660         case AM_HAL_DSP0:
1661             retval = dsp0_memory_get(psConfig);
1662             break;
1663         case AM_HAL_DSP1:
1664             retval = dsp1_memory_get(psConfig);
1665             break;
1666     }
1667 
1668     return retval;
1669 } // am_hal_pwrctrl_dsp_memory_config_get()
1670 
1671 #if AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
1672 // ****************************************************************************
1673 //
1674 //  crypto_boost_trims()
1675 //
1676 // ****************************************************************************
1677 void
crypto_boost_trims(bool bBoost,int32_t i32VddActAdj)1678 crypto_boost_trims( bool bBoost, int32_t i32VddActAdj )
1679 {
1680     int32_t i32VddfActTrim, i32LDOActTrim;
1681 
1682     //
1683     // Make sure we need to do something.
1684     //
1685     if ( (bBoost && g_bBoostForCryptoApplied) || (!bBoost && !g_bBoostForCryptoApplied) )
1686     {
1687         return;
1688     }
1689 
1690     AM_CRITICAL_BEGIN
1691 
1692     g_bBoostForCryptoApplied = bBoost;
1693 
1694     //
1695     // Handle the buck active boost.
1696     //
1697     g_i32LatestVddfActTrim = bBoost ? g_i32LatestVddfActTrim + i32VddActAdj
1698                                     : g_i32LatestVddfActTrim - i32VddActAdj;
1699     i32VddfActTrim = g_i32LatestVddfActTrim;
1700 
1701     if ( i32VddfActTrim < 0 )
1702     {
1703         i32VddfActTrim = 0;
1704     }
1705     else if ( i32VddfActTrim > MAX_ACTTRIMVDDF )
1706     {
1707         i32VddfActTrim = MAX_ACTTRIMVDDF;
1708     }
1709 
1710     //
1711     // Handle the mem LDO active boost.
1712     //
1713     g_i32LatestLDOActTrim = bBoost ? g_i32LatestLDOActTrim + i32VddActAdj
1714                                    : g_i32LatestLDOActTrim - i32VddActAdj;
1715     i32LDOActTrim = g_i32LatestLDOActTrim;
1716 
1717     if ( i32LDOActTrim < 0 )
1718     {
1719         i32LDOActTrim = 0;
1720     }
1721     else if ( i32LDOActTrim > MAX_MEMLDOACTIVETRIM )
1722     {
1723         i32LDOActTrim = MAX_MEMLDOACTIVETRIM;
1724     }
1725 
1726     if ( bBoost )
1727     {
1728         //
1729         // Boost Simobuck first
1730         //
1731         MCUCTRL->SIMOBUCK12_b.ACTTRIMVDDF = i32VddfActTrim;
1732         am_hal_delay_us(AM_HAL_PWRCTRL_VDDF_BOOST_DELAY);
1733 
1734         //
1735         // Boost VDDF LDO after simobuck
1736         //
1737         MCUCTRL->LDOREG2_b.MEMLDOACTIVETRIM = i32LDOActTrim;
1738     }
1739     else
1740     {
1741         //
1742         // Reduce VDDF LDO first
1743         //
1744         MCUCTRL->LDOREG2_b.MEMLDOACTIVETRIM = i32LDOActTrim;
1745         am_hal_delay_us(AM_HAL_PWRCTRL_MEMLDO_BOOST_DELAY);
1746 
1747         //
1748         // Reduce Simobuck
1749         //
1750         MCUCTRL->SIMOBUCK12_b.ACTTRIMVDDF = i32VddfActTrim;
1751     }
1752 
1753     AM_CRITICAL_END
1754 
1755 #if ( AM_HAL_PWRCTRL_VDDF_BOOST_DELAY >= AM_HAL_PWRCTRL_MEMLDO_BOOST_DELAY )
1756     // Use the longer delay
1757     am_hal_delay_us(AM_HAL_PWRCTRL_VDDF_BOOST_DELAY);
1758 #else
1759     am_hal_delay_us(AM_HAL_PWRCTRL_MEMLDO_BOOST_DELAY);
1760 #endif
1761 
1762 } // crypto_boost_trims()
1763 #endif // AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
1764 
1765 //******************************************************************************
1766 //
1767 // Function that waits for crypto peripheral to stabilize before or after
1768 // powerup/powerdown.
1769 //
1770 //******************************************************************************
1771 #define CRYPTO_WAIT_USEC        100
1772 static uint32_t
crypto_quiesce(void)1773 crypto_quiesce(void)
1774 {
1775     uint32_t ui32Status;
1776 
1777     //
1778     // Wait for crypto block idle.
1779     //
1780     ui32Status = am_hal_delay_us_status_change(CRYPTO_WAIT_USEC,
1781                                                 (uint32_t)&CRYPTO->HOSTCCISIDLE,
1782                                                 CRYPTO_HOSTCCISIDLE_HOSTCCISIDLE_Msk,
1783                                                 CRYPTO_HOSTCCISIDLE_HOSTCCISIDLE_Msk);
1784     if (AM_HAL_STATUS_SUCCESS != ui32Status)
1785     {
1786         return ui32Status;
1787     }
1788 
1789     //
1790     // Wait for OTP idle.
1791     //
1792     ui32Status = am_hal_delay_us_status_change(CRYPTO_WAIT_USEC,
1793                                                (uint32_t)&CRYPTO->NVMISIDLE,
1794                                                CRYPTO_NVMISIDLE_NVMISIDLEREG_Msk,
1795                                                CRYPTO_NVMISIDLE_NVMISIDLEREG_Msk);
1796     if (AM_HAL_STATUS_SUCCESS != ui32Status)
1797     {
1798         return ui32Status;
1799     }
1800 
1801     //
1802     // Alert the CRYPTO block of imminent power down.
1803     //
1804     CRYPTO->HOSTPOWERDOWN_b.HOSTPOWERDOWN = 1;
1805 
1806     return AM_HAL_STATUS_SUCCESS;
1807 } // crypto_quiesce()
1808 
1809 // ****************************************************************************
1810 //
1811 //  am_hal_pwrctrl_periph_enable()
1812 //  Enable power for a peripheral.
1813 //
1814 // ****************************************************************************
1815 uint32_t
am_hal_pwrctrl_periph_enable(am_hal_pwrctrl_periph_e ePeripheral)1816 am_hal_pwrctrl_periph_enable(am_hal_pwrctrl_periph_e ePeripheral)
1817 {
1818     uint32_t      ui32Status;
1819     struct am_pwr_s pwr_ctrl;
1820 
1821     ui32Status = am_get_pwrctrl(&pwr_ctrl, ePeripheral);
1822 
1823     if ( AM_HAL_STATUS_SUCCESS != ui32Status )
1824     {
1825         return ui32Status;
1826     }
1827 
1828     if ( AM_REGVAL(pwr_ctrl.ui32PwrEnRegAddr) & pwr_ctrl.ui32PeriphEnable )
1829     {
1830         //
1831         // We're already enabled, nothing to do.
1832         //
1833         return AM_HAL_STATUS_SUCCESS;
1834     }
1835 
1836 #if AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
1837     if ( ePeripheral == AM_HAL_PWRCTRL_PERIPH_CRYPTO )
1838     {
1839         //
1840         // Before enabling Crypto, make sure voltages have been boosted
1841         //
1842         if ( g_ui32VDDFAdjustCodes != 0 )
1843         {
1844             crypto_boost_trims( true, g_ui32VDDFAdjustCodes );
1845         }
1846     }
1847 #endif // AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
1848 
1849     //
1850     // Enable power control for the given device.
1851     //
1852     AM_CRITICAL_BEGIN
1853     AM_REGVAL(pwr_ctrl.ui32PwrEnRegAddr) |=
1854         pwr_ctrl.ui32PeriphEnable;
1855     AM_CRITICAL_END
1856 
1857     ui32Status = am_hal_delay_us_status_check(AM_HAL_PWRCTRL_MAX_WAIT_US,
1858                                               pwr_ctrl.ui32PwrStatReqAddr,
1859                                               pwr_ctrl.ui32PeriphStatus,
1860                                               pwr_ctrl.ui32PeriphStatus,
1861                                               true);
1862 
1863     //
1864     // Check for timeout.
1865     //
1866     if (AM_HAL_STATUS_SUCCESS != ui32Status)
1867     {
1868 #if AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
1869         if ( ePeripheral == AM_HAL_PWRCTRL_PERIPH_CRYPTO )
1870         {
1871             //
1872             // Crypto enable was not successful after all, so revert the boost.
1873             //
1874             if ( g_ui32VDDFAdjustCodes != 0 )
1875             {
1876                 crypto_boost_trims( false, g_ui32VDDFAdjustCodes );
1877             }
1878         }
1879 #endif // AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
1880 
1881         return ui32Status;
1882     }
1883 
1884     //
1885     // Crypto peripheral needs more time to power up after the normal status bit
1886     // is set. We'll wait for the IDLE signal from the NVM as our signal that
1887     // crypto is ready.
1888     //
1889     if (ePeripheral == AM_HAL_PWRCTRL_PERIPH_CRYPTO)
1890     {
1891         ui32Status = am_hal_delay_us_status_change(CRYPTO_WAIT_USEC,
1892                                                    (uint32_t)&CRYPTO->NVMISIDLE,
1893                                                    CRYPTO_NVMISIDLE_NVMISIDLEREG_Msk,
1894                                                    CRYPTO_NVMISIDLE_NVMISIDLEREG_Msk);
1895 
1896         if (AM_HAL_STATUS_SUCCESS != ui32Status)
1897         {
1898             return ui32Status;
1899         }
1900     }
1901 
1902     //
1903     // Check the device status.
1904     //
1905     if ( (AM_REGVAL(pwr_ctrl.ui32PwrStatReqAddr) &
1906         pwr_ctrl.ui32PeriphStatus) != 0)
1907     {
1908         return AM_HAL_STATUS_SUCCESS;
1909     }
1910     else
1911     {
1912         return AM_HAL_STATUS_FAIL;
1913     }
1914 } // am_hal_pwrctrl_periph_enable()
1915 
1916 // ****************************************************************************
1917 //
1918 //  am_hal_pwrctrl_periph_disable_msk_check()
1919 //  Function checks the PWRCTRL->DEVPWREN
1920 //
1921 //  The original check of ((PWRCTRL->DEVPWRSTATUS & ui32PeriphStatus) == 0)
1922 //      will fail when more than one enable in the same domain is set and the
1923 //      user tries disable only one.
1924 //
1925 // ****************************************************************************
1926 static uint32_t
pwrctrl_periph_disable_msk_check(am_hal_pwrctrl_periph_e ePeripheral)1927 pwrctrl_periph_disable_msk_check(am_hal_pwrctrl_periph_e ePeripheral)
1928 {
1929     uint32_t      ui32Status;
1930     struct am_pwr_s pwr_ctrl;
1931 
1932     ui32Status = am_get_pwrctrl(&pwr_ctrl, ePeripheral);
1933 
1934     if ( AM_HAL_STATUS_SUCCESS != ui32Status )
1935     {
1936         return ui32Status;
1937     }
1938 
1939     switch (pwr_ctrl.ui32PeriphStatus)
1940     {
1941         case (PWRCTRL_HCPA_DEVPWRSTATUS_MASK):
1942             if (((AM_REGVAL(pwr_ctrl.ui32PwrEnRegAddr) & PWRCTRL_HCPA_DEVPWREN_MASK) != 0) &&
1943                 ((AM_REGVAL(pwr_ctrl.ui32PwrEnRegAddr) & pwr_ctrl.ui32PeriphEnable) == 0))
1944             {
1945                 ui32Status = AM_HAL_STATUS_SUCCESS;
1946             }
1947             break;
1948 
1949         case (PWRCTRL_HCPB_DEVPWRSTATUS_MASK):
1950             if (((AM_REGVAL(pwr_ctrl.ui32PwrEnRegAddr) & PWRCTRL_HCPB_DEVPWREN_MASK) != 0) &&
1951                 ((AM_REGVAL(pwr_ctrl.ui32PwrEnRegAddr) & pwr_ctrl.ui32PeriphEnable) == 0))
1952             {
1953                 ui32Status = AM_HAL_STATUS_SUCCESS;
1954             }
1955             break;
1956 
1957         case (PWRCTRL_HCPC_DEVPWRSTATUS_MASK):
1958             if (((AM_REGVAL(pwr_ctrl.ui32PwrEnRegAddr) & PWRCTRL_HCPC_DEVPWREN_MASK) != 0) &&
1959                 ((AM_REGVAL(pwr_ctrl.ui32PwrEnRegAddr) & pwr_ctrl.ui32PeriphEnable) == 0))
1960             {
1961                 ui32Status = AM_HAL_STATUS_SUCCESS;
1962             }
1963             break;
1964 
1965         case (PWRCTRL_MSPI_DEVPWRSTATUS_MASK):
1966             if (((AM_REGVAL(pwr_ctrl.ui32PwrEnRegAddr) & PWRCTRL_MSPI_DEVPWREN_MASK) != 0) &&
1967                 ((AM_REGVAL(pwr_ctrl.ui32PwrEnRegAddr) & pwr_ctrl.ui32PeriphEnable) == 0))
1968             {
1969                 ui32Status = AM_HAL_STATUS_SUCCESS;
1970             }
1971             break;
1972 
1973         case (PWRCTRL_AUD_DEVPWRSTATUS_MASK):
1974             if (((AM_REGVAL(pwr_ctrl.ui32PwrEnRegAddr) & PWRCTRL_AUD_DEVPWREN_MASK) != 0) &&
1975                 ((AM_REGVAL(pwr_ctrl.ui32PwrEnRegAddr) & pwr_ctrl.ui32PeriphEnable) == 0))
1976             {
1977                 ui32Status = AM_HAL_STATUS_SUCCESS;
1978             }
1979             break;
1980 
1981         default:
1982             break;
1983     }
1984 
1985     return ui32Status;
1986 }
1987 
1988 // ****************************************************************************
1989 //
1990 //  am_hal_pwrctrl_periph_disable()
1991 //  Disable power for a peripheral.
1992 //
1993 // ****************************************************************************
1994 uint32_t
am_hal_pwrctrl_periph_disable(am_hal_pwrctrl_periph_e ePeripheral)1995 am_hal_pwrctrl_periph_disable(am_hal_pwrctrl_periph_e ePeripheral)
1996 {
1997     uint32_t      ui32Status;
1998     struct am_pwr_s pwr_ctrl;
1999 
2000     ui32Status = am_get_pwrctrl(&pwr_ctrl, ePeripheral);
2001 
2002     if ( AM_HAL_STATUS_SUCCESS != ui32Status )
2003     {
2004         return ui32Status;
2005     }
2006 
2007     if ( !(AM_REGVAL(pwr_ctrl.ui32PwrEnRegAddr) & pwr_ctrl.ui32PeriphEnable) )
2008     {
2009         //
2010         // We're already disabled, nothing to do.
2011         //
2012         return AM_HAL_STATUS_SUCCESS;
2013     }
2014 
2015     //
2016     // The crypto block needs to be idle before it can be shut down. First,
2017     // we'll check to make sure crypto is actually on by checking the
2018     // peripheral ID bits (otherwise the next step would fault). If CRYPTO is
2019     // on, we poll to make sure NVM is inactive before setting the
2020     // HOSTPOWERDOWN bit to start the shutdown process.
2021     //
2022     if (ePeripheral == AM_HAL_PWRCTRL_PERIPH_CRYPTO)
2023     {
2024         if (CRYPTO->PERIPHERALID0 == 0xC0)
2025         {
2026             ui32Status = crypto_quiesce();
2027 
2028             if (AM_HAL_STATUS_SUCCESS != ui32Status)
2029             {
2030                 return ui32Status;
2031             }
2032 
2033 #if AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
2034             //
2035             // After disabling Crypto, remove the voltage boost
2036             //
2037             if ( g_ui32VDDFAdjustCodes != 0 )
2038             {
2039                 crypto_boost_trims( false, g_ui32VDDFAdjustCodes );
2040             }
2041 #endif // AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
2042         }
2043     }
2044 
2045     //
2046     // The peripheral is not AM_HAL_PWRCTRL_PERIPH_CRYPTO.
2047     // Disable power domain for the given device.
2048     //
2049     AM_CRITICAL_BEGIN
2050     AM_REGVAL(pwr_ctrl.ui32PwrEnRegAddr) &= ~pwr_ctrl.ui32PeriphEnable;
2051     AM_CRITICAL_END
2052 
2053     //
2054     //  This check will fail when more than one enable in the same domain
2055     //      is set and the user tries to disable only one.
2056     //
2057     ui32Status = am_hal_delay_us_status_check(AM_HAL_PWRCTRL_MAX_WAIT_US,
2058                                               pwr_ctrl.ui32PwrStatReqAddr,
2059                                               pwr_ctrl.ui32PeriphStatus,
2060                                               pwr_ctrl.ui32PeriphStatus,
2061                                               false);
2062 
2063     //
2064     // Check for success.
2065     //
2066     if (AM_HAL_STATUS_SUCCESS == ui32Status)
2067     {
2068         return ui32Status;
2069     }
2070     else
2071     {
2072         return pwrctrl_periph_disable_msk_check(ePeripheral);
2073     }
2074 
2075 } // am_hal_pwrctrl_periph_disable()
2076 
2077 // ****************************************************************************
2078 //
2079 //  am_hal_pwrctrl_periph_enabled()
2080 //  Determine whether a peripheral is currently enabled.
2081 //
2082 // ****************************************************************************
2083 uint32_t
am_hal_pwrctrl_periph_enabled(am_hal_pwrctrl_periph_e ePeripheral,bool * bEnabled)2084 am_hal_pwrctrl_periph_enabled(am_hal_pwrctrl_periph_e ePeripheral,
2085                               bool *bEnabled)
2086 {
2087     uint32_t      ui32Status;
2088     struct am_pwr_s pwr_ctrl;
2089 
2090 #ifndef AM_HAL_DISABLE_API_VALIDATION
2091     if ( bEnabled == NULL )
2092     {
2093         return AM_HAL_STATUS_INVALID_ARG;
2094     }
2095 #endif // AM_HAL_DISABLE_API_VALIDATION
2096 
2097     //
2098     // Initialize bEnabled to false in case an error is encountered.
2099     //
2100     *bEnabled = false;
2101 
2102     ui32Status = am_get_pwrctrl(&pwr_ctrl, ePeripheral);
2103 
2104     if ( AM_HAL_STATUS_SUCCESS != ui32Status )
2105     {
2106         return ui32Status;
2107     }
2108 
2109     *bEnabled = ((AM_REGVAL(pwr_ctrl.ui32PwrStatReqAddr) &
2110                   pwr_ctrl.ui32PeriphStatus) != 0);
2111 
2112     return AM_HAL_STATUS_SUCCESS;
2113 
2114 } // am_hal_pwrctrl_periph_enabled()
2115 
2116 // ****************************************************************************
2117 //
2118 //  am_hal_pwrctrl_status_get()
2119 //  Get the current powercontrol status registers.
2120 //
2121 // ****************************************************************************
2122 uint32_t
am_hal_pwrctrl_status_get(am_hal_pwrctrl_status_t * psStatus)2123 am_hal_pwrctrl_status_get(am_hal_pwrctrl_status_t *psStatus)
2124 {
2125     //
2126     // Device Power ON Status
2127     //
2128     psStatus->ui32Device = PWRCTRL->DEVPWRSTATUS;
2129 
2130     //
2131     // Audio Subsystem ON Status
2132     //
2133     psStatus->ui32AudioSS = PWRCTRL->AUDSSPWRSTATUS;
2134 
2135     //
2136     // MCU Memory Power ON Status
2137     //
2138     psStatus->ui32Memory = PWRCTRL->MEMPWRSTATUS;
2139 
2140     //
2141     // Power ON Status for MCU and DSP0/1 Cores
2142     //
2143     psStatus->ui32System = PWRCTRL->SYSPWRSTATUS;
2144 
2145     //
2146     // Shared SRAM Power ON Status
2147     //
2148     psStatus->ui32SSRAM = PWRCTRL->SSRAMPWRST;
2149 
2150     //
2151     // DSP0 Memories Power ON Status
2152     //
2153     psStatus->ui32DSP0MemStatus = PWRCTRL->DSP0MEMPWRST;
2154 
2155     //
2156     // DSP1 Memories Power ON Status
2157     //
2158     psStatus->ui32DSP1MemStatus = PWRCTRL->DSP1MEMPWRST;
2159 
2160     //
2161     // Voltage Regulators status
2162     //
2163     psStatus->ui32VRStatus = PWRCTRL->VRSTATUS;
2164 
2165     //
2166     // Power Status Register for ADC Block
2167     //
2168     psStatus->ui32ADC = PWRCTRL->ADCSTATUS;
2169 
2170     //
2171     // Power Status Register for audio ADC Block
2172     //
2173     psStatus->ui32AudioADC = PWRCTRL->AUDADCSTATUS;
2174 
2175     return AM_HAL_STATUS_SUCCESS;
2176 } // am_hal_pwrctrl_status_get()
2177 
2178 // ****************************************************************************
2179 //
2180 //  am_hal_pwrctrl_low_power_init()
2181 //  Initialize the device for low power operation.
2182 //
2183 // ****************************************************************************
2184 uint32_t
am_hal_pwrctrl_low_power_init(void)2185 am_hal_pwrctrl_low_power_init(void)
2186 {
2187 #if AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
2188     uint32_t ui32Ret, ui32PatchTracker;
2189 
2190     //
2191     // Determine the initial state of Crypto.
2192     //
2193     g_bBoostForCryptoApplied = PWRCTRL->DEVPWRSTATUS_b.PWRSTCRYPTO ? true : false;
2194 #endif // AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
2195 
2196     //
2197     // Set the default memory configuration.
2198     //
2199     am_hal_pwrctrl_mcu_memory_config((am_hal_pwrctrl_mcu_memory_config_t *)&g_DefaultMcuMemCfg);
2200     am_hal_pwrctrl_sram_config((am_hal_pwrctrl_sram_memcfg_t *)&g_DefaultSRAMCfg);
2201 
2202     //
2203     // Enable clock gate optimizations for Apollo4.
2204     //
2205     CLKGEN->MISC |=
2206         _VAL2FLD(CLKGEN_MISC_CM4DAXICLKGATEEN, 1)       |   // [18] CM4 DAXI CLK
2207         _VAL2FLD(CLKGEN_MISC_GFXCLKCLKGATEEN, 1)        |   // [19] GFX CLK
2208         _VAL2FLD(CLKGEN_MISC_GFXAXICLKCLKGATEEN, 1)     |   // [20] GFX AXI CLK
2209         _VAL2FLD(CLKGEN_MISC_APBDMACPUCLKCLKGATEEN, 1)  |   // [21] APB DMA CPU CLK
2210         _VAL2FLD(CLKGEN_MISC_ETMTRACECLKCLKGATEEN, 1)   |   // [22] ETM TRACE CLK
2211         _VAL2FLD(CLKGEN_MISC_HFRCFUNCCLKGATEEN, 1);         // [23] HFRC_FUNC_CLK
2212 
2213     //
2214     // Set the PWRCTRL PWRWEIGHTS all to 0's.
2215     //
2216     PWRCTRL->PWRWEIGHTULP0  = 0;
2217     PWRCTRL->PWRWEIGHTULP1  = 0;
2218     PWRCTRL->PWRWEIGHTULP2  = 0;
2219     PWRCTRL->PWRWEIGHTULP3  = 0;
2220     PWRCTRL->PWRWEIGHTULP4  = 0;
2221     PWRCTRL->PWRWEIGHTULP5  = 0;
2222     PWRCTRL->PWRWEIGHTLP0   = 0;
2223     PWRCTRL->PWRWEIGHTLP1   = 0;
2224     PWRCTRL->PWRWEIGHTLP2   = 0;
2225     PWRCTRL->PWRWEIGHTLP3   = 0;
2226     PWRCTRL->PWRWEIGHTLP4   = 0;
2227     PWRCTRL->PWRWEIGHTLP5   = 0;
2228     PWRCTRL->PWRWEIGHTHP0   = 0;
2229     PWRCTRL->PWRWEIGHTHP1   = 0;
2230     PWRCTRL->PWRWEIGHTHP2   = 0;
2231     PWRCTRL->PWRWEIGHTHP3   = 0;
2232     PWRCTRL->PWRWEIGHTHP4   = 0;
2233     PWRCTRL->PWRWEIGHTHP5   = 0;
2234     PWRCTRL->PWRWEIGHTSLP   = 0;
2235 
2236     //
2237     //  Set up the Default DAXICFG.
2238     //
2239     am_hal_daxi_config(&am_hal_daxi_defaults);
2240     am_hal_delay_us(100);
2241 
2242     //
2243     // Additional required settings
2244     //
2245     CLKGEN->MISC_b.PWRONCLKENDISP = 1;
2246 
2247     //
2248     // Initialize DSPRAM, SSRAM trims for proper retention operation.
2249     //
2250     MCUCTRL->PWRSW0 |=  _VAL2FLD(MCUCTRL_PWRSW0_PWRSWVDDMDSP0DYNSEL, 1)     |
2251                         _VAL2FLD(MCUCTRL_PWRSW0_PWRSWVDDMDSP0OVERRIDE, 1)   |
2252                         _VAL2FLD(MCUCTRL_PWRSW0_PWRSWVDDMDSP1DYNSEL, 1)     |
2253                         _VAL2FLD(MCUCTRL_PWRSW0_PWRSWVDDMDSP1OVERRIDE, 1)   |
2254                         _VAL2FLD(MCUCTRL_PWRSW0_PWRSWVDDMLDYNSEL, 1)        |
2255                         _VAL2FLD(MCUCTRL_PWRSW0_PWRSWVDDMLOVERRIDE, 1)      |
2256                         _VAL2FLD(MCUCTRL_PWRSW0_PWRSWVDDMCPUDYNSEL, 1)      |
2257                         _VAL2FLD(MCUCTRL_PWRSW0_PWRSWVDDMCPUOVERRIDE, 1)    |
2258                         _VAL2FLD(MCUCTRL_PWRSW0_PWRSWVDDMDSP0STATSEL, 1)    |
2259                         _VAL2FLD(MCUCTRL_PWRSW0_PWRSWVDDMDSP1STATSEL, 1);
2260 
2261     // Increases the reference recovery time between scans in LPMODE1 from 5us to 10us.
2262     MCUCTRL->AUDADCPWRDLY_b.AUDADCPWR1 = 4;
2263 
2264     //
2265     // Store the factory values for various trims.
2266     //
2267     if ( g_bOrigTrimsStored == false )
2268     {
2269         g_orig_ACTTRIMVDDF          = MCUCTRL->SIMOBUCK12_b.ACTTRIMVDDF;
2270         g_orig_MEMLDOACTIVETRIM     = MCUCTRL->LDOREG2_b.MEMLDOACTIVETRIM;
2271         g_orig_LPTRIMVDDF           = MCUCTRL->SIMOBUCK12_b.LPTRIMVDDF;
2272         g_orig_MEMLPLDOTRIM         = MCUCTRL->LDOREG2_b.MEMLPLDOTRIM;
2273         g_orig_TVRGVREFTRIM         = MCUCTRL->VREFGEN2_b.TVRGVREFTRIM;
2274         g_orig_CORELDOACTIVETRIM    = MCUCTRL->LDOREG1_b.CORELDOACTIVETRIM;
2275         g_bOrigTrimsStored          = true;
2276     }
2277 
2278 #if AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
2279     //
2280     // Initialize the global active trims
2281     //
2282     g_i32LatestVddfActTrim = g_orig_ACTTRIMVDDF;
2283     g_i32LatestLDOActTrim  = g_orig_MEMLDOACTIVETRIM;
2284 
2285     //
2286     // Get trimrev version
2287     //
2288     g_ui32VDDFAdjustCodes = 0;
2289 
2290     //
2291     // Determine the appropriate trimming adjustments by checking the
2292     // patch tracking level that has been applied to the device.
2293     //
2294     ui32Ret = am_hal_mram_info_read(1, AM_REG_INFO1_PATCH_TRACKER0_O / 4, 1, &ui32PatchTracker);
2295     if ( ui32Ret == 0 )
2296     {
2297         //
2298         // Determine the boost amount based on the patch level.
2299         //
2300         if ( (ui32PatchTracker & (0x3 << 1)) == 0 )
2301         {
2302             g_ui32VDDFAdjustCodes = 3;
2303         }
2304         else if ( (ui32PatchTracker & (0x1 << 1)) == 0 )
2305         {
2306             g_ui32VDDFAdjustCodes = 6;
2307         }
2308         else if ( (ui32PatchTracker & (0x1 << 2)) == 0 )
2309         {
2310             g_ui32VDDFAdjustCodes = 9;
2311         }
2312         else
2313         {
2314             g_ui32VDDFAdjustCodes = 0;
2315         }
2316     }
2317 #endif // AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
2318 
2319     return AM_HAL_STATUS_SUCCESS;
2320 
2321 } // am_hal_pwrctrl_low_power_init()
2322 
2323 void
buck_ldo_override_init(void)2324 buck_ldo_override_init(void)
2325 {
2326     //
2327     // Force SIMOBUCK into active mode. SIMOBUCKOVER must be set last.
2328     // This override, even though enabled - is not effective till we go to DeepSleep
2329     //
2330     MCUCTRL->VRCTRL_b.SIMOBUCKPDNB   = 1;
2331     MCUCTRL->VRCTRL_b.SIMOBUCKRSTB   = 1;
2332     MCUCTRL->VRCTRL_b.SIMOBUCKACTIVE = 1;
2333     MCUCTRL->VRCTRL_b.SIMOBUCKOVER   = 1;
2334 
2335 #if AM_HAL_PWRCTL_SET_CORELDO_MEMLDO_IN_PARALLEL
2336     //
2337     // Force LDOs into active mode and to run in parallel with SIMO.
2338     //
2339     //
2340     // Core LDO. Set CORELDOOVER last
2341     //
2342     MCUCTRL->VRCTRL_b.CORELDOCOLDSTARTEN  = 0;
2343     MCUCTRL->VRCTRL |=
2344         MCUCTRL_VRCTRL_CORELDOACTIVE_Msk        |
2345         MCUCTRL_VRCTRL_CORELDOACTIVEEARLY_Msk   |
2346         MCUCTRL_VRCTRL_CORELDOPDNB_Msk;
2347     MCUCTRL->VRCTRL_b.CORELDOOVER         = 1;
2348     //
2349     // Mem LDO. Set MEMLDOOVER last
2350     //
2351     MCUCTRL->VRCTRL_b.MEMLDOCOLDSTARTEN   = 0;
2352     MCUCTRL->VRCTRL |=
2353         MCUCTRL_VRCTRL_MEMLDOACTIVE_Msk         |
2354         MCUCTRL_VRCTRL_MEMLDOACTIVEEARLY_Msk    |
2355         MCUCTRL_VRCTRL_MEMLDOPDNB_Msk;
2356     MCUCTRL->VRCTRL_b.MEMLDOOVER          = 1;
2357 #endif // AM_HAL_PWRCTL_SET_CORELDO_MEMLDO_IN_PARALLEL
2358 } // buck_ldo_override_init()
2359 
2360 
2361 // Dynamically turn on and off the overrides for buck and LDO
2362 // Override configs are already set once in buck_ldo_override_init
2363 void
buck_ldo_update_override(bool bEnable)2364 buck_ldo_update_override(bool bEnable)
2365 {
2366     MCUCTRL->VRCTRL_b.SIMOBUCKOVER   = bEnable;
2367 #if AM_HAL_PWRCTL_SET_CORELDO_MEMLDO_IN_PARALLEL
2368     MCUCTRL->VRCTRL_b.CORELDOOVER    = bEnable;
2369     MCUCTRL->VRCTRL_b.MEMLDOOVER     = bEnable;
2370 #endif // AM_HAL_PWRCTL_SET_CORELDO_MEMLDO_IN_PARALLEL
2371 } // buck_ldo_update_override()
2372 
2373 // ****************************************************************************
2374 //
2375 //  am_hal_pwrctrl_control()
2376 //  Additional miscellaneous power controls.
2377 //
2378 // ****************************************************************************
2379 uint32_t
am_hal_pwrctrl_control(am_hal_pwrctrl_control_e eControl,void * pArgs)2380 am_hal_pwrctrl_control(am_hal_pwrctrl_control_e eControl, void *pArgs)
2381 {
2382     uint32_t ui32ReturnStatus = AM_HAL_STATUS_SUCCESS;
2383     uint32_t ui32TrimVer = 0;
2384     switch ( eControl )
2385     {
2386         case AM_HAL_PWRCTRL_CONTROL_SIMOBUCK_INIT:
2387 
2388             TrimVersionGet(&ui32TrimVer);
2389 
2390             //
2391             // Apply specific trim optimization for SIMOBUCK.
2392             //
2393             if ( ui32TrimVer < TRIMREV_PCM )
2394             {
2395                 //
2396                 // Set zero crossing for comparator to best value.
2397                 //
2398                 MCUCTRL->SIMOBUCK15_b.ZXCOMPOFFSETTRIM  = 0;
2399                 MCUCTRL->SIMOBUCK7_b.ZXCOMPZXTRIM       = 0;
2400 
2401                 //
2402                 // Set Set VDDC active low and high TON trim.
2403                 //
2404                 MCUCTRL->SIMOBUCK2_b.VDDCACTLOWTONTRIM  = 0xA;
2405                 MCUCTRL->SIMOBUCK2_b.VDDCACTHIGHTONTRIM = 0xA;
2406 
2407                 //
2408                 // Set VDDF active low and high TON trim.
2409                 //
2410                 MCUCTRL->SIMOBUCK7_b.VDDFACTLOWTONTRIM  = 0xF;
2411                 MCUCTRL->SIMOBUCK6_b.VDDFACTHIGHTONTRIM = 0xF;
2412 
2413                 //
2414                 // Set VDDS active low and high TON trim.
2415                 //
2416                 MCUCTRL->SIMOBUCK9_b.VDDSACTLOWTONTRIM  = 0xF;
2417                 MCUCTRL->SIMOBUCK9_b.VDDSACTHIGHTONTRIM = 0xF;
2418             }
2419 
2420             //
2421             // Update VDDF LP trims
2422             //
2423             MCUCTRL->SIMOBUCK3_b.VDDCLPLOWTONTRIM  = 0xA;
2424             MCUCTRL->SIMOBUCK3_b.VDDCLPHIGHTONTRIM = 0xA;
2425             MCUCTRL->SIMOBUCK8_b.VDDFLPLOWTONTRIM  = 0xF;
2426             MCUCTRL->SIMOBUCK8_b.VDDFLPHIGHTONTRIM = 0xF;
2427 
2428 #if AM_HAL_PWRCTL_SHORT_VDDF_TO_VDDS
2429             //
2430             // Enable VDDF to VDDS short to increase load cap (2.2uF + 2.2uF).
2431             //
2432             MCUCTRL->PWRSW1_b.SHORTVDDFVDDSORVAL  = 1;
2433             MCUCTRL->PWRSW1_b.SHORTVDDFVDDSOREN   = 1;
2434 
2435             g_ui32origSimobuckVDDStrim = MCUCTRL->SIMOBUCK13_b.ACTTRIMVDDS;
2436             MCUCTRL->SIMOBUCK13_b.ACTTRIMVDDS = 0;    // VDDS trim level to 0
2437 #endif // AM_HAL_PWRCTL_SHORT_VDDF_TO_VDDS
2438 
2439             //
2440             // Enable VDDC, VDDF, and VDDS.
2441             //
2442             MCUCTRL->SIMOBUCK0  =   _VAL2FLD(MCUCTRL_SIMOBUCK0_VDDCRXCOMPEN, 1) |
2443                                     _VAL2FLD(MCUCTRL_SIMOBUCK0_VDDSRXCOMPEN, 1) |
2444                                     _VAL2FLD(MCUCTRL_SIMOBUCK0_VDDFRXCOMPEN, 1);
2445 
2446             if ( ui32TrimVer < TRIMREV_PCM )
2447             {
2448                 //
2449                 // Set SIMOBUCK clock.
2450                 //
2451                 MCUCTRL->SIMOBUCK1_b.TONCLKTRIM       = 0;
2452                 MCUCTRL->SIMOBUCK1_b.RXCLKACTTRIM     = 1;
2453             }
2454 #if AM_HAL_PWRCTRL_CORE_PWR_OPTIMAL_EFFICIENCY
2455             if ( ui32TrimVer >= TRIMREV_PWRCTRL )
2456             {
2457                 //
2458                 // Connect MCU core to VDDC_LV for increased power efficiency.
2459                 //
2460                 // Enable the VDDC_LV rail
2461                 //
2462                 MCUCTRL->SIMOBUCK0 =
2463                     MCUCTRL_SIMOBUCK0_VDDCLVRXCOMPEN_Msk    |   // VDDC LV rail
2464                     MCUCTRL_SIMOBUCK0_VDDSRXCOMPEN_Msk      |   // VDDS rail
2465                     MCUCTRL_SIMOBUCK0_VDDFRXCOMPEN_Msk      |   // VDDF rail
2466                     MCUCTRL_SIMOBUCK0_VDDCRXCOMPEN_Msk;         // VDDC rail
2467 
2468                 //
2469                 // Connect the MCU core to run from the VDDC_LV rail in order
2470                 // to reduce power consumption when active.
2471                 //
2472                 MCUCTRL->D2ASPARE &=
2473                     ~(MCUCTRL_D2ASPARE_VDDCPUOVERRIDE_Msk   |
2474                       MCUCTRL_D2ASPARE_VDDCAOROVERRIDE_Msk);
2475             }
2476 #endif // AM_HAL_PWRCTRL_CORE_PWR_OPTIMAL_EFFICIENCY
2477 
2478 #ifdef AM_HAL_PWRCTL_SHORT_VDDC_TO_VDDCLV
2479         //
2480         // This keeps the VDDC_LV cap from charging and discharging
2481         //
2482         MCUCTRL->PWRSW1_b.SHORTVDDCVDDCLVOREN  = 1; //<! bit 28
2483         MCUCTRL->PWRSW1_b.SHORTVDDCVDDCLVORVAL = 1; //<! bit 29
2484 #endif
2485 
2486             //
2487             // Enable the SIMOBUCK
2488             //
2489             PWRCTRL->VRCTRL_b.SIMOBUCKEN = 1;
2490 
2491             //
2492             // Allow dynamic SIMOBUCK trim adjustments
2493             //
2494             MCUCTRL->SIMOBUCK15_b.TRIMLATCHOVER = 1;
2495 
2496             // Initialize the Buck and LDO override settings, and enable overrides
2497             buck_ldo_override_init();
2498             break;
2499 
2500         case AM_HAL_PWRCTRL_CONTROL_CRYPTO_POWERDOWN:
2501             {
2502                 uint32_t    ui32Status;
2503                 bool        bEnabled;
2504 
2505                 //
2506                 // Check if CRYPTO block is powered on.
2507                 //
2508                 bEnabled = false;
2509                 am_hal_pwrctrl_periph_enabled(AM_HAL_PWRCTRL_PERIPH_CRYPTO, &bEnabled);
2510                 if ( bEnabled )
2511                 {
2512                     //
2513                     // Power down the crypto block in case it was left on by SBR/SBL.
2514                     //
2515                     ui32Status = am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_CRYPTO);
2516                     if (AM_HAL_STATUS_SUCCESS != ui32Status)
2517                     {
2518                         return ui32Status;
2519                     }
2520                 }
2521             }
2522             break;
2523 
2524         case AM_HAL_PWRCTRL_CONTROL_XTAL_PWDN_DEEPSLEEP:
2525             //
2526             // This optimization is optional. Enable it IFF the 32KHz crystal is
2527             // not required during deep sleep. If enabled it will save ~0.8uA.
2528             //
2529             MCUCTRL->XTALGENCTRL_b.XTALBIASTRIM   = 0x20;
2530 
2531             MCUCTRL->XTALCTRL =
2532                 _VAL2FLD(MCUCTRL_XTALCTRL_XTALICOMPTRIM,  0 )                                       |
2533                 _VAL2FLD(MCUCTRL_XTALCTRL_XTALIBUFTRIM,   0 )                                       |
2534                 _VAL2FLD(MCUCTRL_XTALCTRL_XTALCOMPPDNB,   MCUCTRL_XTALCTRL_XTALCOMPPDNB_PWRDNCOMP ) |
2535                 _VAL2FLD(MCUCTRL_XTALCTRL_XTALPDNB,       MCUCTRL_XTALCTRL_XTALPDNB_PWRDNCORE )     |
2536                 _VAL2FLD(MCUCTRL_XTALCTRL_XTALCOMPBYPASS, MCUCTRL_XTALCTRL_XTALCOMPBYPASS_USECOMP ) |
2537                 _VAL2FLD(MCUCTRL_XTALCTRL_XTALCOREDISFB,  MCUCTRL_XTALCTRL_XTALCOREDISFB_EN )       |
2538                 _VAL2FLD(MCUCTRL_XTALCTRL_XTALSWE,        MCUCTRL_XTALCTRL_XTALSWE_OVERRIDE_EN);
2539             break;
2540 
2541         case AM_HAL_PWRCTRL_CONTROL_DIS_PERIPHS_ALL:
2542             PWRCTRL->DEVPWREN =
2543                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENDBG,     PWRCTRL_DEVPWREN_PWRENDBG_DIS)          |
2544                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUSBPHY,  PWRCTRL_DEVPWREN_PWRENUSBPHY_DIS)       |
2545                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUSB,     PWRCTRL_DEVPWREN_PWRENUSB_DIS)          |
2546                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENSDIO,    PWRCTRL_DEVPWREN_PWRENSDIO_DIS)         |
2547                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENCRYPTO,  PWRCTRL_DEVPWREN_PWRENCRYPTO_DIS)       |
2548                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENDISPPHY, PWRCTRL_DEVPWREN_PWRENDISPPHY_DIS)      |
2549                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENDISP,    PWRCTRL_DEVPWREN_PWRENDISP_DIS)         |
2550                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENGFX,     PWRCTRL_DEVPWREN_PWRENGFX_DIS)          |
2551                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENMSPI2,   PWRCTRL_DEVPWREN_PWRENMSPI2_DIS)        |
2552                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENMSPI1,   PWRCTRL_DEVPWREN_PWRENMSPI1_DIS)        |
2553                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENMSPI0,   PWRCTRL_DEVPWREN_PWRENMSPI0_DIS)        |
2554                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENADC,     PWRCTRL_DEVPWREN_PWRENADC_DIS)          |
2555                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUART3,   PWRCTRL_DEVPWREN_PWRENUART3_DIS)        |
2556                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUART2,   PWRCTRL_DEVPWREN_PWRENUART2_DIS)        |
2557                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUART1,   PWRCTRL_DEVPWREN_PWRENUART1_DIS)        |
2558                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENUART0,   PWRCTRL_DEVPWREN_PWRENUART0_DIS)        |
2559                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM7,    PWRCTRL_DEVPWREN_PWRENIOM7_DIS)         |
2560                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM6,    PWRCTRL_DEVPWREN_PWRENIOM6_DIS)         |
2561                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM5,    PWRCTRL_DEVPWREN_PWRENIOM5_DIS)         |
2562                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM4,    PWRCTRL_DEVPWREN_PWRENIOM4_DIS)         |
2563                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM3,    PWRCTRL_DEVPWREN_PWRENIOM3_DIS)         |
2564                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM2,    PWRCTRL_DEVPWREN_PWRENIOM2_DIS)         |
2565                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM1,    PWRCTRL_DEVPWREN_PWRENIOM1_DIS)         |
2566                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOM0,    PWRCTRL_DEVPWREN_PWRENIOM0_DIS)         |
2567                 _VAL2FLD(PWRCTRL_DEVPWREN_PWRENIOS,     PWRCTRL_DEVPWREN_PWRENIOS_DIS);
2568             break;
2569 
2570 #if AM_HAL_TEMPCO_LP
2571         case AM_HAL_PWRCTRL_CONTROL_TEMPCO_GETMEASTEMP:
2572             if ( pArgs )
2573             {
2574                 *((float*)pArgs) = g_pfTempMeasured;
2575             }
2576 #endif // AM_HAL_TEMPCO_LP
2577 
2578         default:
2579             ui32ReturnStatus = AM_HAL_STATUS_INVALID_ARG;
2580             break;
2581     }
2582 
2583     //
2584     // Return success status.
2585     //
2586     return ui32ReturnStatus;
2587 
2588 } // am_hal_pwrctrl_control()
2589 
2590 // ****************************************************************************
2591 // Function to restore factory trims.
2592 // ****************************************************************************
2593 static void
restore_factory_trims(void)2594 restore_factory_trims(void)
2595 {
2596     if ( g_bOrigTrimsStored )
2597     {
2598         //
2599         // Restore the original factory trim values
2600         //
2601         MCUCTRL->SIMOBUCK12_b.ACTTRIMVDDF    = g_orig_ACTTRIMVDDF;
2602         MCUCTRL->LDOREG2_b.MEMLDOACTIVETRIM  = g_orig_MEMLDOACTIVETRIM;
2603         MCUCTRL->SIMOBUCK12_b.LPTRIMVDDF     = g_orig_LPTRIMVDDF;
2604         MCUCTRL->LDOREG2_b.MEMLPLDOTRIM      = g_orig_MEMLPLDOTRIM;
2605         MCUCTRL->VREFGEN2_b.TVRGVREFTRIM     = g_orig_TVRGVREFTRIM;
2606         MCUCTRL->LDOREG1_b.CORELDOACTIVETRIM = g_orig_CORELDOACTIVETRIM;
2607     }
2608 } // restore_factory_trims()
2609 
2610 //*****************************************************************************
2611 //
2612 // Restore original power settings
2613 //
2614 // This function restores default power trims, reverting relative changes that
2615 // were done as part of am_hal_pwrctrl_low_power_init, SIMOBUCK init, and
2616 // dynamic updates such as are made with Temperature Compensation (TempCo)
2617 // and/or by enabling Crypto.
2618 //
2619 // Important:
2620 // - This function must be called before transition to a new application, such
2621 //   as the case of a secondary bootloader transistioning to an application.
2622 // - If previously enabled, TempCo must be disabled before this function is
2623 //   called.
2624 //
2625 // - This function switches from SIMOBUCK to LDO which is known to affect
2626 //   VDDC and VDDC_LV
2627 //   Please see AM_HAL_PWRCTL_SHORT_VDDC_TO_VDDCLV in am_hal_pwrctrl.h.
2628 //
2629 //*****************************************************************************
2630 uint32_t
am_hal_pwrctrl_settings_restore(void)2631 am_hal_pwrctrl_settings_restore(void)
2632 {
2633     uint32_t ui32Ret;
2634 
2635     //
2636     // Ensure - we're in LP mode
2637     //
2638     if (PWRCTRL->MCUPERFREQ_b.MCUPERFREQ != AM_HAL_PWRCTRL_MCU_MODE_LOW_POWER)
2639     {
2640         // Device needs to be in LP mode before restore is called
2641         return AM_HAL_STATUS_INVALID_OPERATION;
2642     }
2643 
2644     //
2645     // Need to revert the trim changes, and turn to LDO mode
2646     //
2647     AM_CRITICAL_BEGIN
2648 
2649     //
2650     // Switch to LDO mode (if not already in LDO mode)
2651     // Delay 20us for rails to settle
2652     //
2653     if (PWRCTRL->VRSTATUS_b.SIMOBUCKST == PWRCTRL_VRSTATUS_SIMOBUCKST_ACT)
2654     {
2655 #if AM_HAL_PWRCTL_SHORT_VDDF_TO_VDDS
2656         if (g_ui32origSimobuckVDDStrim != 0xFFFFFFFF)
2657         {
2658             MCUCTRL->SIMOBUCK13_b.ACTTRIMVDDS = g_ui32origSimobuckVDDStrim;
2659         }
2660 
2661         //
2662         // Remove VDDS/VDDF short
2663         //
2664         MCUCTRL->PWRSW1_b.SHORTVDDFVDDSORVAL  = 0;
2665         MCUCTRL->PWRSW1_b.SHORTVDDFVDDSOREN   = 0;
2666 #endif
2667 
2668         PWRCTRL->VRCTRL_b.SIMOBUCKEN = 0;
2669         // Need to remove overrides
2670         buck_ldo_update_override(false);
2671     }
2672 
2673     //
2674     // Re-enable Crypto if not already on.
2675     // The enable function will check whether it's enabled or not.
2676     //
2677     ui32Ret = am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_CRYPTO);
2678 
2679     //
2680     // Restore original factory trims.
2681     // This will apply whether or not AM_HAL_TEMPCO_LP is activated.
2682     //
2683     restore_factory_trims();
2684 
2685     AM_CRITICAL_END
2686 
2687     return ui32Ret;
2688 
2689 } // am_hal_pwrctrl_settings_restore()
2690 
2691 #if AM_HAL_TEMPCO_LP
2692 // ****************************************************************************
2693 //
2694 //  am_hal_pwrctrl_tempco_init()
2695 //  ui32UpdateInterval - Time in seconds. 10 is recommended.
2696 //
2697 //  User must also call am_hal_adc_initialize().
2698 //
2699 // ****************************************************************************
2700 uint32_t
am_hal_pwrctrl_tempco_init(void * pADCHandle,uint32_t ui32ADCslot)2701 am_hal_pwrctrl_tempco_init(void *pADCHandle,
2702                            uint32_t ui32ADCslot)
2703 {
2704     uint32_t                    ui32Retval;
2705     am_hal_adc_slot_config_t    sSlotCfg;
2706     uint32_t ui32TrimVer;
2707 
2708     uint32_t ui32Temp[3];
2709 
2710     //
2711     // First make sure the temperature calibration is valid.
2712     // am_hal_mram_info_read(INFOn, word_offset, num_wds, variable)
2713     //
2714     ui32Retval = am_hal_mram_info_read(1, AM_REG_INFO1_TEMP_CAL_ATE_O / 4, 3, &ui32Temp[0]);
2715     if ( (ui32Retval != 0)           || (ui32Temp[0] == 0xFFFFFFFF) ||
2716          (ui32Temp[1] == 0xFFFFFFFF) || (ui32Temp[2] == 0xFFFFFFFF) )
2717     {
2718         //
2719         // Invalidate the application of TempCo.
2720         //
2721         g_bTempcoValid = false;
2722         return AM_HAL_STATUS_HW_ERR;
2723     }
2724 
2725     //
2726     // Make sure this device can reliably support TempCo
2727     //
2728     TrimVersionGet(&ui32TrimVer);
2729     if ( ui32TrimVer < TRIMREV_PWRCTRL )
2730     {
2731         //
2732         // Invalidate that original trims have been saved, which
2733         // invalidates the application of TempCo.
2734         //
2735         //
2736         // Invalidate the application of TempCo.
2737         //
2738         g_bTempcoValid = false;
2739         return AM_HAL_STATUS_FAIL;
2740     }
2741     else
2742     {
2743         g_bTempcoValid = true;
2744     }
2745 
2746     //
2747     // Save the ADC handle and the slot number.
2748     //
2749     g_TempcoADCHandle   = pADCHandle;
2750     g_ui32TempcoADCslot = ui32ADCslot;
2751 
2752     //
2753     // At this point the ADC is expected to be initialized, powered, and configured.
2754     // Configure the temperature slot.
2755     //
2756     sSlotCfg.eMeasToAvg     = AM_HAL_ADC_SLOT_AVG_1;
2757     sSlotCfg.ui32TrkCyc     = 32;
2758     sSlotCfg.ePrecisionMode = AM_HAL_ADC_SLOT_12BIT;
2759     sSlotCfg.eChannel       = AM_HAL_ADC_SLOT_CHSEL_TEMP;
2760     sSlotCfg.bWindowCompare = false;
2761     sSlotCfg.bEnabled       = true;
2762     ui32Retval = am_hal_adc_configure_slot(g_TempcoADCHandle, g_ui32TempcoADCslot, &sSlotCfg);
2763     if ( ui32Retval != AM_HAL_STATUS_SUCCESS )
2764     {
2765        return ui32Retval;
2766     }
2767 
2768     return AM_HAL_STATUS_SUCCESS;
2769 
2770 } // am_hal_pwrctrl_tempco_init()
2771 
2772 //
2773 // TempCo trims lookup tables
2774 // The VDD table is arranged row-by-row with 3 values as:
2775 //  0: Min temperature
2776 //  1: Max temperature
2777 //  2: Trim code adjust
2778 //
2779 
2780 const static int8_t
2781 g_VDDC_trimstbl[][3] =
2782 {
2783     { -20, 60,    0},
2784     {  60, 90,  -16},   // Last actual table entry
2785     { 127, 127,   0}    // End of table: Probably bogus temp, do no adjustment
2786 };
2787 
2788 //
2789 //! Trim adjust table for VDDF
2790 //
2791 const static int8_t
2792 g_VDDF_trimstbl[][3] =
2793 {
2794     { -20, -11,   0},
2795     { -11,  -2,  -1},
2796     {  -2,   8,  -2},
2797     {   8,  17,  -3},
2798     {  17,  26,  -4},
2799     {  26,  35,  -5},
2800     {  35,  44,  -6},
2801     {  44,  53,  -7},
2802     {  53,  60,  -8},
2803     {  60,  90,  -9},   // Last actual table entry
2804     { 127, 127,   0}    // End of table: Probably bogus temp, do no adjustment
2805 };
2806 
2807 //
2808 //! Trim adjust table for VDDFLP
2809 //
2810 const static int8_t
2811 g_VDDFLP_trimstbl[][3] =
2812 {
2813     { -20, -11,   0},
2814     { -11,  -2,  -1},
2815     {  -2,   8,  -2},
2816     {   8,  17,  -3},
2817     {  17,  26,  -4},
2818     {  26,  35,  -5},
2819     {  35,  44,  -6},
2820     {  44,  53,  -7},
2821     {  53,  60,  -8},
2822     {  60,  90,  -9},   // Last actual table entry
2823     { 127, 127,   0}    // End of table: Probably bogus temp, do no adjustment
2824 };
2825 
2826 //
2827 //! Trim adjust table for memlpldo
2828 //
2829 const static int8_t
2830 g_memlpldo_trimstbl[][3] =
2831 {
2832     { -18, -14,   8},
2833     { -14, -10,   7},
2834     { -10,  -6,   6},
2835     {  -6,  -2,   5},
2836     {  -2,   2,   4},
2837     {   2,   6,   3},
2838     {   6,  10,   2},
2839     {  10,  14,   1},
2840     {  14,  18,   0},
2841     {  18,  22,  -1},
2842     {  22,  26,  -2},
2843     {  26,  42,  -3},
2844     {  42,  60,  -4},
2845     {  60,  90,  -5},   // Last actual table entry
2846     { 127, 127,   0}    // End of table: Probably bogus temp, do no adjustment
2847 };
2848 
2849 //
2850 //! Helper macro to round a float down.
2851 //
2852 #define FTOI_RNDDN(fval)        ( (fval < 0.00F) ? (int)fval - 1 : (int)fval )
2853 
2854 // ****************************************************************************
2855 // Function to lookup a trim given a temperature and a pointer
2856 // to the appropriate lookup table.
2857 // ****************************************************************************
2858 static int8_t
lookup_trim(int8_t i8Temp,const int8_t pi8Tbl[][3])2859 lookup_trim(int8_t i8Temp, const int8_t pi8Tbl[][3])
2860 {
2861     uint32_t ux;
2862     if ( i8Temp < pi8Tbl[0][0] )
2863     {
2864         //
2865         // Return the trim for the lowest temperature in the table
2866         //
2867         return pi8Tbl[0][2];
2868     }
2869     else
2870     {
2871         //
2872         // Lookup the trim
2873         //
2874         ux = 0;
2875         while ( pi8Tbl[ux][0] < 127 )
2876         {
2877             if ( i8Temp <= pi8Tbl[ux][1] )
2878             {
2879                 return pi8Tbl[ux][2];
2880             }
2881             ux++;
2882         }
2883 
2884         //
2885         // The temperature is very high, so snap to the default trims
2886         ///
2887         return 0;
2888     }
2889 
2890 } // lookup_trim()
2891 
2892 // ****************************************************************************
2893 // Function to validate and apply trim changes.
2894 // ****************************************************************************
2895 static void
tempco_set_trims(int32_t i32VDDFtrim,int32_t i32VDDFLPtrim,int32_t i32MemlpLDOtrim,int32_t i32VDDCtrim)2896 tempco_set_trims(int32_t i32VDDFtrim,
2897                  int32_t i32VDDFLPtrim,
2898                  int32_t i32MemlpLDOtrim,
2899                  int32_t i32VDDCtrim)
2900 {
2901     int32_t i32SimoVDDFact, i32Memldoact, i32SimoVDDFlp, i32Memlpldo, i32TvrgVref, i32CoreMemldoact;
2902 
2903     if ( !g_bOrigTrimsStored )
2904     {
2905         return;
2906     }
2907 
2908     i32SimoVDDFact   = g_orig_ACTTRIMVDDF       + i32VDDFtrim;
2909     i32Memldoact     = g_orig_MEMLDOACTIVETRIM  + i32VDDFtrim;
2910     i32SimoVDDFlp    = g_orig_LPTRIMVDDF        + i32VDDFLPtrim;
2911     i32Memlpldo      = g_orig_MEMLPLDOTRIM      + i32MemlpLDOtrim;
2912     i32TvrgVref      = g_orig_TVRGVREFTRIM      + i32VDDCtrim;
2913     i32CoreMemldoact = g_orig_CORELDOACTIVETRIM + i32VDDCtrim;
2914 
2915     //
2916     // If Crypto is currently off, adjust the VDDF active trim.
2917     //
2918     AM_CRITICAL_BEGIN
2919 
2920 #if AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
2921     if ( !g_bBoostForCryptoApplied )
2922     {
2923         //
2924         // When Crypto is off, subtract from the factory codes for VDDF active
2925         // (both simobuck and memldo) to save power.
2926         //
2927         i32SimoVDDFact -= g_ui32VDDFAdjustCodes;
2928         i32Memldoact   -= g_ui32VDDFAdjustCodes;
2929     }
2930 
2931     //
2932     // Save the trim values
2933     //
2934     g_i32LatestVddfActTrim = i32SimoVDDFact;
2935     g_i32LatestLDOActTrim  = i32Memldoact;
2936 #endif // AM_HAL_PWRCTL_OPTIMIZE_ACTIVE_TRIMS_CRYPTO
2937 
2938     if ( i32SimoVDDFact < 0 )
2939     {
2940         i32SimoVDDFact = 0;
2941     }
2942     else if ( i32SimoVDDFact > MAX_ACTTRIMVDDF )
2943     {
2944         i32SimoVDDFact = MAX_ACTTRIMVDDF;
2945     }
2946 
2947     if ( i32Memldoact < 0 )
2948     {
2949         i32Memldoact = 0;
2950     }
2951     else if ( i32Memldoact > MAX_MEMLDOACTIVETRIM )
2952     {
2953         i32Memldoact = MAX_MEMLDOACTIVETRIM;
2954     }
2955 
2956     if ( i32SimoVDDFlp < 0 )
2957     {
2958         i32SimoVDDFlp = 0;
2959     }
2960     else if ( i32SimoVDDFlp > MAX_LPTRIMVDDF )
2961     {
2962         i32SimoVDDFlp = MAX_LPTRIMVDDF;
2963     }
2964 
2965     if ( i32Memlpldo  < 0 )
2966     {
2967         i32Memlpldo  = 0;
2968     }
2969     else if ( i32Memlpldo > MAX_MEMLPLDOTRIM )
2970     {
2971         i32Memlpldo = MAX_MEMLPLDOTRIM;
2972     }
2973 
2974     if ( i32TvrgVref  < 0 )
2975     {
2976         i32TvrgVref  = 0;
2977     }
2978     else if ( i32TvrgVref > MAX_TVRGVREFTRIM )
2979     {
2980         i32TvrgVref = MAX_TVRGVREFTRIM;
2981     }
2982 
2983     if ( i32CoreMemldoact  < 0 )
2984     {
2985         i32CoreMemldoact  = 0;
2986     }
2987     else if ( i32CoreMemldoact > MAX_CORELDOACTIVETRIM )
2988     {
2989         i32CoreMemldoact = MAX_CORELDOACTIVETRIM;
2990     }
2991 
2992     //
2993     // Now set the new values
2994     //
2995     MCUCTRL->SIMOBUCK12_b.ACTTRIMVDDF    = i32SimoVDDFact;
2996     MCUCTRL->LDOREG2_b.MEMLDOACTIVETRIM  = i32Memldoact;
2997     MCUCTRL->SIMOBUCK12_b.LPTRIMVDDF     = i32SimoVDDFlp;
2998     MCUCTRL->LDOREG2_b.MEMLPLDOTRIM      = i32Memlpldo;
2999     MCUCTRL->VREFGEN2_b.TVRGVREFTRIM     = i32TvrgVref;
3000     MCUCTRL->LDOREG1_b.CORELDOACTIVETRIM = i32CoreMemldoact;
3001 
3002     AM_CRITICAL_END
3003 } // tempco_set_trims()
3004 
3005 // ****************************************************************************
3006 // Validate samples from temperature sensor, and average them.
3007 // ****************************************************************************
3008 static uint32_t
adc_get_temperature_volts(float * pfADCTempVolts,uint32_t ui32NumSamples,am_hal_adc_sample_t sSample[])3009 adc_get_temperature_volts(float *pfADCTempVolts,
3010                           uint32_t ui32NumSamples,
3011                           am_hal_adc_sample_t sSample[])
3012 {
3013     uint32_t ux;
3014     float fSum;
3015 
3016     //
3017     // ui32NumSamples temperature samples have been obtained.
3018     // Make sure at least 2 of the samples are slightly different.
3019     //
3020     ux = 0;
3021     while ( ux < (ui32NumSamples - 1) )
3022     {
3023         if ( sSample[ux].ui32Sample != sSample[ux + 1].ui32Sample )
3024         {
3025             break;
3026         }
3027         ux++;
3028     }
3029 
3030     if ( ux == (ui32NumSamples - 1) )
3031     {
3032         //
3033         // This sample is not reliable, return with error.
3034         //
3035         return AM_HAL_STATUS_FAIL;
3036     }
3037 
3038     //
3039     // The measured temperature can be considered reliable.
3040     // Get an average of the temperature.
3041     //
3042     ux = 0;
3043     fSum = 0.0F;
3044     while ( ux < ui32NumSamples )
3045     {
3046         //
3047         // Convert and scale the temperature sample into its corresponding voltage.
3048         //
3049         g_ui16TempcoTEMP_code = AM_HAL_ADC_FIFO_SAMPLE(sSample[ux].ui32Sample);
3050         fSum += (float)g_ui16TempcoTEMP_code * AM_HAL_ADC_VREF / 4096.0f; // 12-bit sample
3051         ux++;
3052     }
3053 
3054     *pfADCTempVolts = fSum / ((float)ui32NumSamples);
3055 
3056     return AM_HAL_STATUS_SUCCESS;
3057 
3058 } // adc_get_temperature_volts()
3059 
3060 // ****************************************************************************
3061 //
3062 //  am_hal_pwrctrl_tempco_sample_handler()
3063 //
3064 //  This function to be called with a minimum periodicity as recommended
3065 //  by Ambiq engineering.
3066 //
3067 // ****************************************************************************
3068 uint32_t
am_hal_pwrctrl_tempco_sample_handler(uint32_t ui32NumSamples,am_hal_adc_sample_t sSamples[])3069 am_hal_pwrctrl_tempco_sample_handler(uint32_t ui32NumSamples, am_hal_adc_sample_t sSamples[])
3070 {
3071     uint32_t ui32Retval;
3072     float fVT[3];
3073     float fADCTempVolts, fADCTempDegreesC;
3074     int32_t i32VDDFtrim, i32VDDFLPtrim, i32MemlpLDOtrim, i32VDDCtrim;
3075 
3076     if ( (g_bTempcoValid == false) || (ui32NumSamples < AM_HAL_TEMPCO_NUMSAMPLES) )
3077     {
3078         return AM_HAL_STATUS_FAIL;
3079     }
3080 
3081     //
3082     // Query the ADC for the current temperature of the chip.
3083     //
3084     ui32Retval = adc_get_temperature_volts(&fADCTempVolts, ui32NumSamples, sSamples);
3085     if ( ui32Retval != AM_HAL_STATUS_SUCCESS )
3086     {
3087         //
3088         // This sample is not reliable.
3089         // Snap to the highest trim code settings from the tables and return.
3090         //
3091         tempco_set_trims(g_VDDF_trimstbl[0][2],
3092                          g_VDDFLP_trimstbl[0][2],
3093                          g_memlpldo_trimstbl[0][2],
3094                          g_VDDC_trimstbl[0][2]);
3095         return ui32Retval;
3096     }
3097 
3098     //
3099     // Now call the HAL routine to convert volts to degrees Celsius.
3100     //
3101     fVT[0] = fADCTempVolts;
3102     fVT[1] = 0.0f;
3103     fVT[2] = -123.456;
3104     ui32Retval = am_hal_adc_control(g_TempcoADCHandle, AM_HAL_ADC_REQ_TEMP_CELSIUS_GET, fVT);
3105     if ( ui32Retval == AM_HAL_STATUS_SUCCESS )
3106     {
3107         fADCTempDegreesC = fVT[1];  // Get the temperature
3108         g_pfTempMeasured = fADCTempDegreesC;
3109     }
3110     else
3111     {
3112         //
3113         // Error, restore default values.
3114         //
3115         tempco_set_trims(0, 0, 0, 0);
3116         g_pfTempMeasured = 0.0F;
3117         return ui32Retval;
3118     }
3119 
3120     //
3121     // The temperature in degC is stored in fADCTempDegreesC
3122     //
3123     int8_t  i8Temp;
3124     int32_t i32Temp;
3125     i32Temp = FTOI_RNDDN(fADCTempDegreesC);
3126 
3127     //
3128     // Get the integer value of the temperature.
3129     // Allow for the temperature sensor specified at +-3C.
3130     //
3131     i8Temp = (int8_t)(i32Temp - 3);
3132 
3133     //
3134     // Look up the 3 trim adjustments.
3135     //
3136     i32VDDFtrim      = (int32_t)lookup_trim(i8Temp, g_VDDF_trimstbl);
3137     i32VDDFLPtrim    = (int32_t)lookup_trim(i8Temp, g_VDDFLP_trimstbl);
3138     i32MemlpLDOtrim  = (int32_t)lookup_trim(i8Temp, g_memlpldo_trimstbl);
3139     i32VDDCtrim      = (int32_t)lookup_trim(i8Temp, g_VDDC_trimstbl);
3140 
3141     //
3142     // Now, set the trims appropriately.
3143     //
3144     tempco_set_trims(i32VDDFtrim, i32VDDFLPtrim, i32MemlpLDOtrim, i32VDDCtrim);
3145 
3146     return AM_HAL_STATUS_SUCCESS;
3147 } // am_hal_pwrctrl_tempco_sample_handler()
3148 
3149 #endif // AM_HAL_TEMPCO_LP
3150 
3151 //*****************************************************************************
3152 //
3153 // End Doxygen group.
3154 //! @}
3155 //
3156 //*****************************************************************************
3157