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