1 //*****************************************************************************
2 //
3 //! @file am_hal_pwrctrl.c
4 //!
5 //! @brief Functions for enabling and disabling power domains.
6 //!
7 //! @addtogroup pwrctrl3p Pwrctrl - Power Control
8 //! @ingroup apollo3p_hal
9 //! @{
10 //
11 //*****************************************************************************
12 
13 //*****************************************************************************
14 //
15 // Copyright (c) 2024, 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_3_2_0-dd5f40c14b of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47 
48 #include <stdint.h>
49 #include <stdbool.h>
50 #include "am_mcu_apollo.h"
51 
52 //*****************************************************************************
53 //
54 //  Defines
55 //
56 //*****************************************************************************
57 //
58 //! Maximum number of checks to memory power status before declaring error.
59 //
60 #define AM_HAL_PWRCTRL_MAX_WAIT     20
61 
62 //*****************************************************************************
63 //
64 //  Globals
65 //
66 //*****************************************************************************
67 bool g_bSimobuckTrimsDone = false;
68 
69 #ifdef AM_HAL_PWRCTRL_VDDF_BOOST_WA
70 bool g_bVddfTrimsDone = false;
71 #endif
72 
73 //
74 //!    Mask of HCPA Enables from the PWRCTRL->DEVPWRSTATUS register mapped to the
75 //!        PWRCTRL->DEVPWREN register
76 //
77 #define HCPA_MASK       ( \
78     _VAL2FLD(PWRCTRL_DEVPWREN_PWRIOS, PWRCTRL_DEVPWREN_PWRIOS_EN) | \
79     _VAL2FLD(PWRCTRL_DEVPWREN_PWRUART0, PWRCTRL_DEVPWREN_PWRUART0_EN) | \
80     _VAL2FLD(PWRCTRL_DEVPWREN_PWRUART1, PWRCTRL_DEVPWREN_PWRUART1_EN) | \
81     _VAL2FLD(PWRCTRL_DEVPWREN_PWRSCARD, PWRCTRL_DEVPWREN_PWRSCARD_EN))
82 
83 //
84 //!    Mask of HCPB Enables from the PWRCTRL->DEVPWRSTATUS register mapped to the
85 //!        PWRCTRL->DEVPWREN register
86 //
87 #define HCPB_MASK       ( \
88     _VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM0, PWRCTRL_DEVPWREN_PWRIOM0_EN) | \
89     _VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM1, PWRCTRL_DEVPWREN_PWRIOM1_EN) | \
90     _VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM2, PWRCTRL_DEVPWREN_PWRIOM2_EN))
91 
92 //
93 //!    Mask of HCPC Enables from the PWRCTRL->DEVPWRSTATUS register mapped to the
94 //!        PWRCTRL->DEVPWREN register
95 //
96 #define HCPC_MASK       ( \
97     _VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM3, PWRCTRL_DEVPWREN_PWRIOM3_EN) | \
98     _VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM4, PWRCTRL_DEVPWREN_PWRIOM4_EN) | \
99     _VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM5, PWRCTRL_DEVPWREN_PWRIOM5_EN))
100 
101 //
102 //!    Mask of MSPI Enables from the PWRCTRL->DEVPWRSTATUS register mapped to the
103 //!        PWRCTRL->DEVPWREN register
104 //
105 #define MSPI_MASK       ( \
106     _VAL2FLD(PWRCTRL_DEVPWREN_PWRMSPI0, PWRCTRL_DEVPWREN_PWRMSPI0_EN) | \
107     _VAL2FLD(PWRCTRL_DEVPWREN_PWRMSPI1, PWRCTRL_DEVPWREN_PWRMSPI1_EN) | \
108     _VAL2FLD(PWRCTRL_DEVPWREN_PWRMSPI2, PWRCTRL_DEVPWREN_PWRMSPI2_EN))
109 
110 //
111 //! Define the peripheral control structure.
112 //
113 const struct
114 {
115     uint32_t      ui32PeriphEnable;
116     uint32_t      ui32PeriphStatus;
117     uint32_t      ui32PeriphEvent;
118 }
119 am_hal_pwrctrl_peripheral_control[AM_HAL_PWRCTRL_PERIPH_MAX] =
120 {
121     {0, 0, 0},                                  //  AM_HAL_PWRCTRL_PERIPH_NONE
122     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRIOS, PWRCTRL_DEVPWREN_PWRIOS_EN),
123      PWRCTRL_DEVPWRSTATUS_HCPA_Msk,
124      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPAEVEN, PWRCTRL_DEVPWREVENTEN_HCPAEVEN_EN)},  // AM_HAL_PWRCTRL_PERIPH_IOS
125     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM0, PWRCTRL_DEVPWREN_PWRIOM0_EN),
126      PWRCTRL_DEVPWRSTATUS_HCPB_Msk,
127      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPBEVEN, PWRCTRL_DEVPWREVENTEN_HCPBEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_IOM0
128     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM1, PWRCTRL_DEVPWREN_PWRIOM1_EN),
129      PWRCTRL_DEVPWRSTATUS_HCPB_Msk,
130      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPBEVEN, PWRCTRL_DEVPWREVENTEN_HCPBEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_IOM1
131     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM2, PWRCTRL_DEVPWREN_PWRIOM2_EN),
132      PWRCTRL_DEVPWRSTATUS_HCPB_Msk,
133      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPBEVEN, PWRCTRL_DEVPWREVENTEN_HCPBEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_IOM2
134     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM3, PWRCTRL_DEVPWREN_PWRIOM3_EN),
135      PWRCTRL_DEVPWRSTATUS_HCPC_Msk,
136      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPCEVEN, PWRCTRL_DEVPWREVENTEN_HCPCEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_IOM3
137     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM4, PWRCTRL_DEVPWREN_PWRIOM4_EN),
138      PWRCTRL_DEVPWRSTATUS_HCPC_Msk,
139      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPCEVEN, PWRCTRL_DEVPWREVENTEN_HCPCEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_IOM4
140     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM5, PWRCTRL_DEVPWREN_PWRIOM5_EN),
141      PWRCTRL_DEVPWRSTATUS_HCPC_Msk,
142      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPCEVEN, PWRCTRL_DEVPWREVENTEN_HCPCEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_IOM5
143     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRUART0, PWRCTRL_DEVPWREN_PWRUART0_EN),
144      PWRCTRL_DEVPWRSTATUS_HCPA_Msk,
145      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPAEVEN, PWRCTRL_DEVPWREVENTEN_HCPAEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_UART0
146     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRUART1, PWRCTRL_DEVPWREN_PWRUART1_EN),
147      PWRCTRL_DEVPWRSTATUS_HCPA_Msk,
148      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPAEVEN, PWRCTRL_DEVPWREVENTEN_HCPAEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_UART1
149     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRADC, PWRCTRL_DEVPWREN_PWRADC_EN),
150      PWRCTRL_DEVPWRSTATUS_PWRADC_Msk,
151      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_ADCEVEN, PWRCTRL_DEVPWREVENTEN_ADCEVEN_EN)},    //  AM_HAL_PWRCTRL_PERIPH_ADC
152     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRSCARD, PWRCTRL_DEVPWREN_PWRSCARD_EN),
153      PWRCTRL_DEVPWRSTATUS_HCPA_Msk,
154      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPAEVEN, PWRCTRL_DEVPWREVENTEN_HCPAEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_SCARD
155     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRMSPI0, PWRCTRL_DEVPWREN_PWRMSPI0_EN),
156      PWRCTRL_DEVPWRSTATUS_PWRMSPI_Msk,
157      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_MSPIEVEN, PWRCTRL_DEVPWREVENTEN_MSPIEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_MSPI0
158     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRMSPI1, PWRCTRL_DEVPWREN_PWRMSPI1_EN),
159      PWRCTRL_DEVPWRSTATUS_PWRMSPI_Msk,
160      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_MSPIEVEN, PWRCTRL_DEVPWREVENTEN_MSPIEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_MSPI1
161     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRMSPI2, PWRCTRL_DEVPWREN_PWRMSPI2_EN),
162      PWRCTRL_DEVPWRSTATUS_PWRMSPI_Msk,
163      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_MSPIEVEN, PWRCTRL_DEVPWREVENTEN_MSPIEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_MSPI2
164     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRPDM, PWRCTRL_DEVPWREN_PWRPDM_EN),
165      PWRCTRL_DEVPWRSTATUS_PWRPDM_Msk,
166      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_PDMEVEN, PWRCTRL_DEVPWREVENTEN_PDMEVEN_EN)},    //  AM_HAL_PWRCTRL_PERIPH_PDM
167     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRBLEL, PWRCTRL_DEVPWREN_PWRBLEL_EN),
168      PWRCTRL_DEVPWRSTATUS_BLEL_Msk,
169      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_BLELEVEN, PWRCTRL_DEVPWREVENTEN_BLELEVEN_EN)}   //  AM_HAL_PWRCTRL_PERIPH_BLEL
170 };
171 
172 //
173 //! Define the memory control structure.
174 //
175 const struct
176 {
177     uint32_t      ui32MemoryEnable;
178     uint32_t      ui32MemoryStatus;
179     uint32_t      ui32MemoryEvent;
180     uint32_t      ui32MemoryMask;
181     uint32_t      ui32StatusMask;
182     uint32_t      ui32PwdSlpEnable;
183 }
184 am_hal_pwrctrl_memory_control[AM_HAL_PWRCTRL_MEM_MAX] =
185 {
186     {0, 0, 0, 0, 0, 0},
187     {AM_HAL_PWRCTRL_MEMEN_SRAM_8K_DTCM,
188      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_8K_DTCM,
189      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_8K_DTCM,
190      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
191      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
192      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_8K_DTCM},
193     {AM_HAL_PWRCTRL_MEMEN_SRAM_32K_DTCM,
194      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_32K_DTCM,
195      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_32K_DTCM,
196      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
197      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
198      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_32K_DTCM},
199     {AM_HAL_PWRCTRL_MEMEN_SRAM_64K_DTCM,
200      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_64K_DTCM,
201      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_64K_DTCM,
202      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
203      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
204      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_64K_DTCM},
205     {AM_HAL_PWRCTRL_MEMEN_SRAM_128K,
206      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_128K,
207      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_128K,
208      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
209      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
210      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_128K},
211     {AM_HAL_PWRCTRL_MEMEN_SRAM_192K,
212      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_192K,
213      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_192K,
214      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
215      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
216      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_192K},
217     {AM_HAL_PWRCTRL_MEMEN_SRAM_256K,
218      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_256K,
219      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_256K,
220      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
221      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
222      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_256K},
223     {AM_HAL_PWRCTRL_MEMEN_SRAM_320K,
224      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_320K,
225      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_320K,
226      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
227      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
228      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_320K},
229     {AM_HAL_PWRCTRL_MEMEN_SRAM_384K,
230      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_384K,
231      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_384K,
232      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
233      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
234      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_384K},
235     {AM_HAL_PWRCTRL_MEMEN_SRAM_448K,
236      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_448K,
237      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_448K,
238      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
239      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
240      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_448K},
241     {AM_HAL_PWRCTRL_MEMEN_SRAM_512K,
242      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_512K,
243      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_512K,
244      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
245      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
246      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_512K},
247     {AM_HAL_PWRCTRL_MEMEN_SRAM_576K,
248      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_576K,
249      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_576K,
250      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
251      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
252      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_576K},
253     {AM_HAL_PWRCTRL_MEMEN_SRAM_672K,
254      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_672K,
255      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_672K,
256      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
257      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
258      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_672K},
259     {AM_HAL_PWRCTRL_MEMEN_SRAM_768K,
260      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_768K,
261      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_768K,
262      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
263      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
264      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_768K},
265     {AM_HAL_PWRCTRL_MEMEN_FLASH_1M,
266      AM_HAL_PWRCTRL_PWRONSTATUS_FLASH_1M,
267      AM_HAL_PWRCTRL_MEMPWREVENTEN_FLASH_1M,
268      AM_HAL_PWRCTRL_MEM_REGION_FLASH_MASK,
269      AM_HAL_PWRCTRL_MEM_REGION_FLASH_MASK,
270      AM_HAL_PWRCTRL_MEMPWDINSLEEP_FLASH_1M},
271     {AM_HAL_PWRCTRL_MEMEN_FLASH_2M,
272      AM_HAL_PWRCTRL_PWRONSTATUS_FLASH_2M,
273      AM_HAL_PWRCTRL_MEMPWREVENTEN_FLASH_2M,
274      AM_HAL_PWRCTRL_MEM_REGION_FLASH_MASK,
275      AM_HAL_PWRCTRL_MEM_REGION_FLASH_MASK,
276      AM_HAL_PWRCTRL_MEMPWDINSLEEP_FLASH_2M},
277     {AM_HAL_PWRCTRL_MEMEN_CACHE,
278      0,
279      AM_HAL_PWRCTRL_MEMPWREVENTEN_CACHE,
280      AM_HAL_PWRCTRL_MEM_REGION_CACHE_MASK,
281      0,
282      AM_HAL_PWRCTRL_MEMPWDINSLEEP_CACHE},
283     {AM_HAL_PWRCTRL_MEMEN_ALL,
284      AM_HAL_PWRCTRL_PWRONSTATUS_ALL,
285      AM_HAL_PWRCTRL_MEMPWREVENTEN_ALL,
286      AM_HAL_PWRCTRL_MEM_REGION_ALL_MASK,
287      AM_HAL_PWRCTRL_MEM_REGION_ALT_ALL_MASK,
288      AM_HAL_PWRCTRL_MEMPWDINSLEEP_ALL}
289 };
290 
291 // ****************************************************************************
292 //
293 //  Enable power for a peripheral.
294 //
295 // ****************************************************************************
296 uint32_t
am_hal_pwrctrl_periph_enable(am_hal_pwrctrl_periph_e ePeripheral)297 am_hal_pwrctrl_periph_enable(am_hal_pwrctrl_periph_e ePeripheral)
298 {
299     //
300     // Enable power control for the given device.
301     //
302     AM_CRITICAL_BEGIN
303     PWRCTRL->DEVPWREN |= am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphEnable;
304     AM_CRITICAL_END
305 
306     for (uint32_t wait_usecs = 0; wait_usecs < AM_HAL_PWRCTRL_MAX_WAIT; wait_usecs += 10)
307     {
308         am_hal_flash_delay(FLASH_CYCLES_US(10));
309 
310         if ((PWRCTRL->DEVPWRSTATUS & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphStatus) > 0)
311         {
312             break;
313         }
314     }
315 
316     //
317     // Check the device status.
318     //
319     if ((PWRCTRL->DEVPWRSTATUS & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphStatus) > 0)
320     {
321         return AM_HAL_STATUS_SUCCESS;
322     }
323     else
324     {
325         //
326         // If the Power Enable fails, make sure the DEVPWREN is Low
327         //
328         AM_CRITICAL_BEGIN
329         PWRCTRL->DEVPWREN &= ~am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphEnable;
330         AM_CRITICAL_END
331 
332         return AM_HAL_STATUS_FAIL;
333     }
334 } // am_hal_pwrctrl_periph_enable()
335 
336 // ****************************************************************************
337 //
338 //  Function checks the PWRCTRL->DEVPWREN since the PWRCTRL->DEVPWRSTATUS
339 //        register alone cannot tell the user if a peripheral is enabled when
340 //        and HCPx register is being used.
341 //
342 // ****************************************************************************
343 static uint32_t
pwrctrl_periph_disable_msk_check(am_hal_pwrctrl_periph_e ePeripheral)344 pwrctrl_periph_disable_msk_check(am_hal_pwrctrl_periph_e ePeripheral)
345 {
346     uint32_t retVal = AM_HAL_STATUS_FAIL;
347     uint32_t HCPxMSPIxMask = PWRCTRL->DEVPWREN;
348 
349     switch (am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphStatus)
350     {
351         case (PWRCTRL_DEVPWRSTATUS_HCPA_Msk):
352             if (((HCPxMSPIxMask & HCPA_MASK) > 0) && ((HCPxMSPIxMask & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphEnable) == 0))
353             {
354                 retVal = AM_HAL_STATUS_SUCCESS;
355             }
356             break;
357 
358         case (PWRCTRL_DEVPWRSTATUS_HCPB_Msk):
359             if (((HCPxMSPIxMask & HCPB_MASK) > 0) && ((HCPxMSPIxMask & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphEnable) == 0))
360             {
361                 retVal = AM_HAL_STATUS_SUCCESS;
362             }
363             break;
364 
365         case (PWRCTRL_DEVPWRSTATUS_HCPC_Msk):
366             if (((HCPxMSPIxMask & HCPC_MASK) > 0) && ((HCPxMSPIxMask & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphEnable) == 0))
367             {
368                 retVal = AM_HAL_STATUS_SUCCESS;
369             }
370             break;
371 
372         case (PWRCTRL_DEVPWRSTATUS_PWRMSPI_Msk):
373             if (((HCPxMSPIxMask & MSPI_MASK) > 0) && ((HCPxMSPIxMask & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphEnable) == 0))
374             {
375                 retVal = AM_HAL_STATUS_SUCCESS;
376             }
377             break;
378 
379         default:
380             break;
381     }
382 
383     return retVal;
384 }
385 
386 // ****************************************************************************
387 //
388 //  Disable power for a peripheral.
389 //
390 // ****************************************************************************
391 uint32_t
am_hal_pwrctrl_periph_disable(am_hal_pwrctrl_periph_e ePeripheral)392 am_hal_pwrctrl_periph_disable(am_hal_pwrctrl_periph_e ePeripheral)
393 {
394     //
395     // Disable power domain for the given device.
396     //
397     AM_CRITICAL_BEGIN
398     PWRCTRL->DEVPWREN &= ~am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphEnable;
399     AM_CRITICAL_END
400 
401     for (uint32_t wait_usecs = 0; wait_usecs < AM_HAL_PWRCTRL_MAX_WAIT; wait_usecs += 10)
402     {
403         am_hal_flash_delay(FLASH_CYCLES_US(10));
404 
405         if ((PWRCTRL->DEVPWRSTATUS & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphStatus) == 0)
406         {
407             break;
408         }
409     }
410 
411     //
412     // Check the device status.
413     //
414     if ((PWRCTRL->DEVPWRSTATUS & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphStatus) == 0)
415     {
416         return AM_HAL_STATUS_SUCCESS;
417     }
418     else
419     {
420         return pwrctrl_periph_disable_msk_check(ePeripheral);
421     }
422 
423 } // am_hal_pwrctrl_periph_disable()
424 
425 //*****************************************************************************
426 //
427 // This function determines to the caller whether a given peripheral is
428 // currently enabled or disabled.
429 //
430 //*****************************************************************************
431 uint32_t
am_hal_pwrctrl_periph_enabled(am_hal_pwrctrl_periph_e ePeripheral,uint32_t * pui32Enabled)432 am_hal_pwrctrl_periph_enabled(am_hal_pwrctrl_periph_e ePeripheral,
433                               uint32_t *pui32Enabled)
434 {
435     uint32_t ui32Mask = am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphStatus;
436     uint32_t ui32Enabled = 0;
437 
438     if (pui32Enabled == NULL)
439     {
440         return AM_HAL_STATUS_INVALID_ARG;
441     }
442 
443     if (ui32Mask != 0)
444     {
445         ui32Enabled = PWRCTRL->DEVPWRSTATUS & ui32Mask ? 1 : 0;
446         ui32Enabled = ui32Enabled && (PWRCTRL->DEVPWREN & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphEnable);
447     }
448 
449     *pui32Enabled = ui32Enabled;
450 
451     return AM_HAL_STATUS_SUCCESS;
452 
453 } // am_hal_pwrctrl_periph_enabled()
454 
455 // ****************************************************************************
456 //
457 //  Enable a configuration of memory.
458 //
459 // ****************************************************************************
460 uint32_t
am_hal_pwrctrl_memory_enable(am_hal_pwrctrl_mem_e eMemConfig)461 am_hal_pwrctrl_memory_enable(am_hal_pwrctrl_mem_e eMemConfig)
462 {
463     uint32_t ui32MemEnMask, ui32MemDisMask, ui32MemRegionMask, ui32MemStatusMask;
464 
465     ui32MemEnMask     =  am_hal_pwrctrl_memory_control[eMemConfig].ui32MemoryEnable;
466     ui32MemDisMask    = ~am_hal_pwrctrl_memory_control[eMemConfig].ui32MemoryEnable;
467     ui32MemRegionMask = am_hal_pwrctrl_memory_control[eMemConfig].ui32MemoryMask;
468     ui32MemStatusMask = am_hal_pwrctrl_memory_control[eMemConfig].ui32StatusMask;
469 
470     //
471     // Disable unneeded memory. If nothing to be disabled, skip to save time.
472     //
473     // Note that a deliberate disable step using a disable mask is taken here
474     // for 2 reasons: 1) To only affect the specified type of memory, and 2)
475     // To avoid inadvertently disabling any memory currently being depended on.
476     //
477     if ( ui32MemDisMask != 0 )
478     {
479         PWRCTRL->MEMPWREN &=
480             ~(ui32MemDisMask & ui32MemRegionMask)                                   |
481              (_VAL2FLD(PWRCTRL_MEMPWREN_DTCM, PWRCTRL_MEMPWREN_DTCM_GROUP0DTCM0)    |
482               _VAL2FLD(PWRCTRL_MEMPWREN_FLASH0, PWRCTRL_MEMPWREN_FLASH0_EN));
483         am_hal_flash_delay(FLASH_CYCLES_US(1));
484     }
485 
486     //
487     // Enable the required memory.
488     //
489     if ( ui32MemEnMask != 0 )
490     {
491         PWRCTRL->MEMPWREN |= ui32MemEnMask;
492 
493         for (uint32_t wait_usecs = 0; wait_usecs < AM_HAL_PWRCTRL_MAX_WAIT; wait_usecs += 10)
494         {
495             am_hal_flash_delay(FLASH_CYCLES_US(10));
496 
497             if ( (PWRCTRL->MEMPWRSTATUS & ui32MemStatusMask) ==
498                   am_hal_pwrctrl_memory_control[eMemConfig].ui32MemoryStatus )
499             {
500                 break;
501             }
502         }
503     }
504 
505     //
506     // Return status based on whether the power control memory status has reached the desired state.
507     //
508     if ( ( PWRCTRL->MEMPWRSTATUS & ui32MemStatusMask) ==
509            am_hal_pwrctrl_memory_control[eMemConfig].ui32MemoryStatus )
510     {
511         return AM_HAL_STATUS_SUCCESS;
512     }
513     else
514     {
515         return AM_HAL_STATUS_FAIL;
516     }
517 
518 } // am_hal_pwrctrl_memory_enable()
519 
520 // ****************************************************************************
521 //
522 //  Power down respective memory.
523 //
524 // ****************************************************************************
525 uint32_t
am_hal_pwrctrl_memory_deepsleep_powerdown(am_hal_pwrctrl_mem_e eMemConfig)526 am_hal_pwrctrl_memory_deepsleep_powerdown(am_hal_pwrctrl_mem_e eMemConfig)
527 {
528     if ( eMemConfig >= AM_HAL_PWRCTRL_MEM_MAX )
529     {
530         return AM_HAL_STATUS_FAIL;
531     }
532 
533     //
534     // Power down the required memory.
535     //
536     PWRCTRL->MEMPWDINSLEEP |= am_hal_pwrctrl_memory_control[eMemConfig].ui32PwdSlpEnable;
537 
538     return AM_HAL_STATUS_SUCCESS;
539 
540 } // am_hal_pwrctrl_memory_deepsleep_powerdown()
541 
542 // ****************************************************************************
543 //
544 //  Apply retention voltage to respective memory.
545 //
546 // ****************************************************************************
547 uint32_t
am_hal_pwrctrl_memory_deepsleep_retain(am_hal_pwrctrl_mem_e eMemConfig)548 am_hal_pwrctrl_memory_deepsleep_retain(am_hal_pwrctrl_mem_e eMemConfig)
549 {
550     if ( eMemConfig >= AM_HAL_PWRCTRL_MEM_MAX )
551     {
552         return AM_HAL_STATUS_FAIL;
553     }
554 
555     //
556     // Retain the required memory.
557     //
558     PWRCTRL->MEMPWDINSLEEP &= ~am_hal_pwrctrl_memory_control[eMemConfig].ui32PwdSlpEnable;
559 
560     return AM_HAL_STATUS_SUCCESS;
561 
562 } // am_hal_pwrctrl_memory_deepsleep_retain()
563 
564 
565 #ifdef AM_HAL_PWRCTRL_VDDF_BOOST_WA
566 //****************************************************************************
567 //
568 //  simobuck_memldo_patch_check()
569 //
570 //****************************************************************************
571 #define AM_REG_INFO1_PATCHVER6_ADDR 0x50023838
572 #define AM_REG_INFO1_TRIM22_ADDR    0x5002386C
573 #define AM_REG_INFO1_TRIM28_ADDR    0x50023870
574 
575 #define TRIM22_MEMLDOACTIVETRIM_Msk 0x0000003F
576 #define TRIM22_MEMLDOACTIVETRIM_Pos 0
577 #define TRIM28_MEMACTIVETRIM_Msk    0x003F0000
578 #define TRIM28_MEMACTIVETRIM_Pos    16
579 
580 static bool
simobuck_memldo_patch_check(void)581 simobuck_memldo_patch_check(void)
582 {
583     //
584     // patch checker bit3 for CV patch
585     //
586     return (AM_REGVAL(AM_REG_INFO1_PATCHVER6_ADDR) & (1 << 3)) ? false : true;
587 } // simobuck_memldo_patch_check
588 
589 //****************************************************************************
590 //
591 //  Apply VDDF boost of +30mV on SIMOBUCK and MEMLDO Active Trim
592 //
593 //****************************************************************************
594 void
am_hal_pwrctrl_bleif_workaround(void)595 am_hal_pwrctrl_bleif_workaround(void)
596 {
597     uint32_t ui32RegBackupVal;
598     uint32_t ui32TrimVal;
599     //
600     // If patch is not applied, use current values for boost.
601     //
602     if (!simobuck_memldo_patch_check())
603     {
604         //
605         // Apply boost based on original values in
606         //   MCUCTRL->SIMOBUCK1 (for simobuck)
607         //   MCUCTRL->LDOREG2   (for MEMLDO)
608         //
609 
610         //
611         // increase VDDF (LDOREG2_MEMLDOACTIVETRIM) by 3 counts
612         //
613         ui32RegBackupVal = MCUCTRL->LDOREG2;
614 
615         ui32TrimVal = _FLD2VAL(MCUCTRL_LDOREG2_MEMLDOACTIVETRIM, ui32RegBackupVal);
616 
617         //
618         // increase VDDF by ui32TrimVal counts
619         //
620         ui32TrimVal += 3;
621 
622         //
623         // check for overflow and limit
624         //
625         ui32TrimVal =  ui32TrimVal > ( MCUCTRL_LDOREG2_MEMLDOACTIVETRIM_Msk >> MCUCTRL_LDOREG2_MEMLDOACTIVETRIM_Pos ) ? ( MCUCTRL_LDOREG2_MEMLDOACTIVETRIM_Msk >> MCUCTRL_LDOREG2_MEMLDOACTIVETRIM_Pos ) : ui32TrimVal;
626 
627         //
628         // Put boosted value back.
629         //
630         MCUCTRL->LDOREG2 &= ~MCUCTRL_LDOREG2_MEMLDOACTIVETRIM_Msk;
631         MCUCTRL->LDOREG2 |= _VAL2FLD(MCUCTRL_LDOREG2_MEMLDOACTIVETRIM, ui32TrimVal);
632 
633         //
634         // increase VDDF (SIMOBUCK1_MEMACTIVETRIM) by 5 counts
635         //
636         ui32RegBackupVal = MCUCTRL->SIMOBUCK1;
637 
638         ui32TrimVal = _FLD2VAL(MCUCTRL_SIMOBUCK1_MEMACTIVETRIM, ui32RegBackupVal);
639 
640         //
641         // increase VDDF by ui32TrimVal counts
642         //
643         ui32TrimVal += 5;
644 
645         //
646         // check for overflow and limit
647         //
648         ui32TrimVal =  ui32TrimVal > ( MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Msk >> MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Pos ) ? ( MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Msk >> MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Pos ) : ui32TrimVal;
649 
650         //
651         // Put boosted value back.
652         //
653         MCUCTRL->SIMOBUCK1 &= ~MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Msk;
654         MCUCTRL->SIMOBUCK1 |= _VAL2FLD(MCUCTRL_SIMOBUCK1_MEMACTIVETRIM, ui32TrimVal);
655     }
656     else
657     {
658         //
659         // Apply boost based on memldo and simobuck_mem_active trims
660         //   AM_REG_INFO1_TRIM28_ADDR & TRIM28_MEMACTIVETRIM_Msk (for simobuck)
661         //   AM_REG_INFO1_TRIM22_ADDR & TRIM22_MEMLDOACTIVETRIM_Msk (for MEMLDO)
662         //
663 
664         //
665         // increase VDDF (MEMLDO) by 3 counts
666         //
667         ui32RegBackupVal = AM_REGVAL(AM_REG_INFO1_TRIM22_ADDR);
668 
669         ui32TrimVal = _FLD2VAL(TRIM22_MEMLDOACTIVETRIM, ui32RegBackupVal);
670 
671         //
672         // increase VDDF by ui32TrimVal counts
673         //
674         ui32TrimVal += 3;
675 
676         //
677         // check for overflow and limit
678         //
679         ui32TrimVal =  ui32TrimVal > (TRIM22_MEMLDOACTIVETRIM_Msk >> TRIM22_MEMLDOACTIVETRIM_Pos) ? (TRIM22_MEMLDOACTIVETRIM_Msk >> TRIM22_MEMLDOACTIVETRIM_Pos) : ui32TrimVal;
680 
681         //
682         // Put boosted value back.
683         //
684         MCUCTRL->LDOREG2 &= ~TRIM22_MEMLDOACTIVETRIM_Msk;
685         MCUCTRL->LDOREG2 |= _VAL2FLD(TRIM22_MEMLDOACTIVETRIM, ui32TrimVal);
686 
687         //
688         // increase VDDF (SIMOBUCK MEM) by 5 counts
689         //
690         ui32RegBackupVal = AM_REGVAL(AM_REG_INFO1_TRIM28_ADDR);
691 
692         ui32TrimVal = _FLD2VAL(TRIM28_MEMACTIVETRIM, ui32RegBackupVal);
693 
694         //
695         // increase VDDF by ui32TrimVal counts
696         //
697         ui32TrimVal += 5;
698 
699         //
700         // check for overflow and limit
701         //
702         ui32TrimVal =  ui32TrimVal > ( TRIM28_MEMACTIVETRIM_Msk >> TRIM28_MEMACTIVETRIM_Pos ) ? ( TRIM28_MEMACTIVETRIM_Msk >> TRIM28_MEMACTIVETRIM_Pos ) : ui32TrimVal;
703 
704         //
705         // Put boosted value back.
706         //
707         MCUCTRL->SIMOBUCK1 &= ~TRIM28_MEMACTIVETRIM_Msk;
708         MCUCTRL->SIMOBUCK1 |= _VAL2FLD(TRIM28_MEMACTIVETRIM, ui32TrimVal);
709     }
710 } //am_hal_pwrctrl_bleif_workaround
711 
712 #endif //#ifdef AM_HAL_PWRCTRL_VDDF_BOOST_WA
713 
714 // ****************************************************************************
715 //
716 //  Updates to the SIMOBUCK Trims
717 //
718 // ****************************************************************************
719 static void
simobuck_updates(void)720 simobuck_updates(void)
721 {
722     //
723     // Adjust the SIMOBUCK LP settings.
724     //
725     if ( APOLLO3_GE_B0 )
726     {
727         if ( !g_bSimobuckTrimsDone )
728         {
729             uint32_t ui32LPTRIM;
730             g_bSimobuckTrimsDone = true;
731 
732             //
733             // Update SIMOBUCK MEM LP TRIM 12 codes ~ -37mV
734             //
735             ui32LPTRIM = MCUCTRL->SIMOBUCK1_b.SIMOBUCKMEMLPTRIM;
736             ui32LPTRIM = ui32LPTRIM > 12 ? ui32LPTRIM - 12 : 0;
737             MCUCTRL->SIMOBUCK1_b.SIMOBUCKMEMLPTRIM = ui32LPTRIM;
738 
739             //
740             // Update SIMOBUCK CORE LP TRIM 13 codes ~ -40mV
741             //
742             ui32LPTRIM = MCUCTRL->SIMOBUCK1_b.SIMOBUCKCORELPTRIM;
743             ui32LPTRIM = ui32LPTRIM > 13 ? ui32LPTRIM - 13 : 0;
744             MCUCTRL->SIMOBUCK1_b.SIMOBUCKCORELPTRIM = ui32LPTRIM;
745 
746             MCUCTRL->SIMOBUCK2_b.SIMOBUCKCORELPLOWTONTRIM   = 8;
747             MCUCTRL->SIMOBUCK2_b.SIMOBUCKCORELPHIGHTONTRIM  = 5;
748             MCUCTRL->SIMOBUCK4_b.SIMOBUCKMEMLPLOWTONTRIM    = 8;
749             MCUCTRL->SIMOBUCK3_b.SIMOBUCKMEMLPHIGHTONTRIM   = 6;
750             MCUCTRL->SIMOBUCK4_b.SIMOBUCKCOMP2LPEN          = 1;
751             MCUCTRL->SIMOBUCK4_b.SIMOBUCKCOMP2TIMEOUTEN     = 0;
752             MCUCTRL->SIMOBUCK2_b.SIMOBUCKCORELEAKAGETRIM    = 3;
753             MCUCTRL->SIMOBUCK2_b.SIMOBUCKTONGENTRIM         = 31;
754         }
755 
756 #ifdef AM_HAL_PWRCTRL_VDDF_BOOST_WA
757         //
758         // Increase VDDF voltage by +30mV for both mem simobuck and ldo
759         //
760         if ( !g_bVddfTrimsDone )
761         {
762             g_bVddfTrimsDone = true;
763 
764             //
765             // Perform boost of vddf by +30mV
766             //
767             am_hal_pwrctrl_bleif_workaround();
768         }
769 #endif //#ifdef AM_HAL_PWRCTRL_VDDF_BOOST_WA
770     }
771 
772     //
773     // Adjust the SIMOBUCK Timeout settings.
774     //
775     if ( APOLLO3_GE_A1 )
776     {
777         MCUCTRL->SIMOBUCK4_b.SIMOBUCKCOMP2TIMEOUTEN = 0;
778     }
779 } // simobuck_updates()
780 
781 // ****************************************************************************
782 //
783 //  am_hal_pwrctrl_low_power_init()
784 //  Initialize system for low power configuration.
785 //
786 // ****************************************************************************
787 uint32_t
am_hal_pwrctrl_low_power_init(void)788 am_hal_pwrctrl_low_power_init(void)
789 {
790     uint32_t      ui32Status;
791 
792     //
793     // Take a snapshot of the reset status, if not done already
794     //
795     if ( !gAmHalResetStatus )
796     {
797         gAmHalResetStatus = RSTGEN->STAT;
798     }
799 
800     //
801     // Adjust the SIMOBUCK LP settings.
802     //
803     simobuck_updates();
804 
805     //
806     // Configure cache for low power and performance.
807     //
808     am_hal_cachectrl_control(AM_HAL_CACHECTRL_CONTROL_LPMMODE_RECOMMENDED, 0);
809 
810     //
811     // Check if the BLE is already enabled.
812     //
813     if ( PWRCTRL->DEVPWRSTATUS_b.BLEL == 0)
814     {
815         am_hal_pwrctrl_blebuck_trim();
816 
817         //
818         // First request the BLE feature and check that it was available and acknowledged.
819         //
820         MCUCTRL->FEATUREENABLE_b.BLEREQ = 1;
821         ui32Status = am_hal_flash_delay_status_check(10000,
822                                                     (uint32_t)&MCUCTRL->FEATUREENABLE,
823                                                     (MCUCTRL_FEATUREENABLE_BLEAVAIL_Msk |
824                                                      MCUCTRL_FEATUREENABLE_BLEACK_Msk   |
825                                                      MCUCTRL_FEATUREENABLE_BLEREQ_Msk),
826                                                     (MCUCTRL_FEATUREENABLE_BLEAVAIL_Msk |
827                                                      MCUCTRL_FEATUREENABLE_BLEACK_Msk   |
828                                                      MCUCTRL_FEATUREENABLE_BLEREQ_Msk),
829                                                      true);
830 
831         if (AM_HAL_STATUS_SUCCESS != ui32Status)
832         {
833             return AM_HAL_STATUS_TIMEOUT;
834         }
835 
836         //
837         // Next, enable the BLE Buck.
838         //
839         PWRCTRL->SUPPLYSRC |= _VAL2FLD(PWRCTRL_SUPPLYSRC_BLEBUCKEN,
840                                        PWRCTRL_SUPPLYSRC_BLEBUCKEN_EN);
841 
842         //
843         // Allow the buck to go to low power mode in BLE sleep.
844         //
845         PWRCTRL->MISC |= _VAL2FLD(PWRCTRL_MISC_MEMVRLPBLE,
846                                   PWRCTRL_MISC_MEMVRLPBLE_EN);
847     }
848 
849 #if AM_HAL_BURST_LDO_WORKAROUND
850     //
851     // This is to charge the capacitor
852     //
853     am_hal_burst_ldo_charge();
854 #endif
855 
856     return AM_HAL_STATUS_SUCCESS;
857 } // am_hal_pwrctrl_low_power_init()
858 
859 // ****************************************************************************
860 //
861 //  am_hal_pwrctrl_blebuck_trim()
862 //
863 // ****************************************************************************
864 void
am_hal_pwrctrl_blebuck_trim(void)865 am_hal_pwrctrl_blebuck_trim(void)
866 {
867     //
868     // Enable the BLE buck trim values
869     //
870     if ( APOLLO3_GE_A1 )
871     {
872         AM_CRITICAL_BEGIN
873         MCUCTRL->BLEBUCK2_b.BLEBUCKTONHITRIM = 0x19;
874         MCUCTRL->BLEBUCK2_b.BLEBUCKTONLOWTRIM = 0xC;
875         CLKGEN->BLEBUCKTONADJ_b.TONADJUSTEN = CLKGEN_BLEBUCKTONADJ_TONADJUSTEN_DIS;
876         AM_CRITICAL_END
877     }
878 } // am_hal_pwrctrl_blebuck_trim()
879 
880 #if AM_HAL_BURST_LDO_WORKAROUND
881 
882 #if 0
883 //****************************************************************************
884 //
885 // Get the simobuck vddc/vddf active trim value with saturation.
886 // Based on current register setting
887 //
888 //****************************************************************************
889 static uint32_t
890 simobuck_vddx_active_trim_get(am_hal_burst_voltage_wa_e vddx)
891 {
892     if (vddx == AM_HAL_BURST_VDDC)
893     {
894         return MCUCTRL->SIMOBUCK1_b.COREACTIVETRIM;
895     }
896     else if (vddx == AM_HAL_BURST_VDDF)
897     {
898         return MCUCTRL->SIMOBUCK1_b.MEMACTIVETRIM;
899     }
900 
901     return 0;
902 }
903 #endif
904 
905 //****************************************************************************
906 //
907 // Get the simobuck vddc/vddf default trim value with saturation.
908 // Based on current register setting
909 //
910 //****************************************************************************
911 static uint32_t
simobuck_vddx_default_trim_get(am_hal_burst_voltage_wa_e vddx)912 simobuck_vddx_default_trim_get(am_hal_burst_voltage_wa_e vddx)
913 {
914     if (am_hal_burst_ldo_patch_check())
915     {
916         if (vddx == AM_HAL_BURST_VDDC)
917         {
918             return (AM_REGVAL(0x50023870) & 0x3FF);
919         }
920         else if (vddx == AM_HAL_BURST_VDDF)
921         {
922             return ((AM_REGVAL(0x50023870) >> 16) & 0x3F);
923         }
924     }
925 
926     return 0;
927 }
928 
929 #if 0
930 //****************************************************************************
931 //
932 // Get the LDO vddc/vddf active trim value with saturation.
933 // Based on current register setting
934 //
935 //****************************************************************************
936 static uint32_t
937 ldo_vddx_active_trim_get(am_hal_burst_voltage_wa_e vddx)
938 {
939     if (vddx == AM_HAL_BURST_VDDC)
940     {
941         return MCUCTRL->LDOREG1_b.CORELDOACTIVETRIM;
942     }
943     else if (vddx == AM_HAL_BURST_VDDF)
944     {
945         return MCUCTRL->LDOREG2_b.MEMLDOACTIVETRIM;
946     }
947 
948     return 0;
949 }
950 #endif
951 
952 //****************************************************************************
953 //
954 // Get the LDO vddc/vddf default trim value with saturation.
955 // Based on current register setting
956 //
957 //****************************************************************************
958 static uint32_t
ldo_vddx_default_trim_get(am_hal_burst_voltage_wa_e vddx)959 ldo_vddx_default_trim_get(am_hal_burst_voltage_wa_e vddx)
960 {
961     if (am_hal_burst_ldo_patch_check())
962     {
963         if (vddx == AM_HAL_BURST_VDDC)
964         {
965             return (AM_REGVAL(0x50023868) & 0x3FF);
966         }
967         else if (vddx == AM_HAL_BURST_VDDF)
968         {
969             return (AM_REGVAL(0x5002386C) & 0x3F);
970         }
971     }
972 
973     return 0;
974 }
975 
976 //****************************************************************************
977 //
978 // Adjust the simobuck vddc/vddf active trim values with saturation.
979 // Based on current register setting
980 // Returns actual adjusted amount of trim code
981 //
982 //****************************************************************************
983 int32_t
am_hal_pwrctrl_simobuck_vddx_active_trim_adj(am_hal_burst_voltage_wa_e vddx,int32_t vddx_code)984 am_hal_pwrctrl_simobuck_vddx_active_trim_adj(am_hal_burst_voltage_wa_e vddx, int32_t vddx_code)
985 {
986     //
987     // save original SIMOBUCK1 value, it will be restored
988     //
989     int32_t i32ActualCode = 0;
990 
991     AM_CRITICAL_BEGIN;
992     if (vddx == AM_HAL_BURST_VDDC)
993     {
994         int32_t i32Vddc = MCUCTRL->SIMOBUCK1_b.COREACTIVETRIM;
995         i32ActualCode = i32Vddc;
996         i32Vddc += vddx_code;
997 
998         //
999         // check for overflow and limit
1000         //
1001         if (i32Vddc < 0)
1002         {
1003             i32Vddc = 0;
1004         }
1005         else if (i32Vddc > (MCUCTRL_SIMOBUCK1_COREACTIVETRIM_Msk >> MCUCTRL_SIMOBUCK1_COREACTIVETRIM_Pos))
1006         {
1007             i32Vddc = (MCUCTRL_SIMOBUCK1_COREACTIVETRIM_Msk >> MCUCTRL_SIMOBUCK1_COREACTIVETRIM_Pos);
1008         }
1009 
1010         i32ActualCode = i32Vddc - i32ActualCode;
1011         MCUCTRL->SIMOBUCK1_b.COREACTIVETRIM = i32Vddc;
1012     }
1013     else if (vddx == AM_HAL_BURST_VDDF)
1014     {
1015         int32_t i32Vddf = MCUCTRL->SIMOBUCK1_b.MEMACTIVETRIM;
1016         i32ActualCode = i32Vddf;
1017         i32Vddf += vddx_code;
1018 
1019         //
1020         // check for overflow and limit
1021         //
1022         if (i32Vddf < 0)
1023         {
1024             i32Vddf = 0;
1025         }
1026         else if (i32Vddf > (MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Msk >> MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Pos))
1027         {
1028             i32Vddf = (MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Msk >> MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Pos);
1029         }
1030 
1031         i32ActualCode = i32Vddf - i32ActualCode;
1032         MCUCTRL->SIMOBUCK1_b.MEMACTIVETRIM = i32Vddf;
1033     }
1034 
1035     am_hal_flash_delay( FLASH_CYCLES_US(20) );
1036     AM_CRITICAL_END;
1037     return i32ActualCode;
1038 }
1039 
1040 //****************************************************************************
1041 //
1042 // Adjust the LDO vddc/vddf active trim values with saturation.
1043 // Based on current register setting
1044 // Returns actual adjusted amount of trim code
1045 //
1046 //****************************************************************************
1047 int32_t
am_hal_pwrctrl_ldo_vddx_active_trim_adj(am_hal_burst_voltage_wa_e vddx,int32_t vddx_code)1048 am_hal_pwrctrl_ldo_vddx_active_trim_adj(am_hal_burst_voltage_wa_e vddx, int32_t vddx_code)
1049 {
1050     //
1051     // save original LDO value, it will be restored
1052     //
1053     int32_t i32ActualCode = 0;
1054 
1055     AM_CRITICAL_BEGIN;
1056     if (vddx == AM_HAL_BURST_VDDC)
1057     {
1058         int32_t i32Vddc = MCUCTRL->LDOREG1_b.CORELDOACTIVETRIM;
1059         i32ActualCode = i32Vddc;
1060         i32Vddc += vddx_code;
1061 
1062         //
1063         // check for overflow and limit
1064         //
1065         if (i32Vddc < 0)
1066         {
1067             i32Vddc = 0;
1068         }
1069         else if (i32Vddc > (MCUCTRL_LDOREG1_CORELDOACTIVETRIM_Msk >> MCUCTRL_LDOREG1_CORELDOACTIVETRIM_Pos))
1070         {
1071             i32Vddc = (MCUCTRL_LDOREG1_CORELDOACTIVETRIM_Msk >> MCUCTRL_LDOREG1_CORELDOACTIVETRIM_Pos);
1072         }
1073 
1074         i32ActualCode = i32Vddc - i32ActualCode;
1075         MCUCTRL->LDOREG1_b.CORELDOACTIVETRIM = i32Vddc;
1076     }
1077     else if (vddx == AM_HAL_BURST_VDDF)
1078     {
1079         int32_t i32Vddf = MCUCTRL->LDOREG2_b.MEMLDOACTIVETRIM;
1080         i32ActualCode = i32Vddf;
1081         i32Vddf += vddx_code;
1082 
1083         //
1084         // check for overflow and limit
1085         //
1086         if (i32Vddf < 0)
1087         {
1088             i32Vddf = 0;
1089         }
1090         else if (i32Vddf > (MCUCTRL_LDOREG2_MEMLDOACTIVETRIM_Msk >> MCUCTRL_LDOREG2_MEMLDOACTIVETRIM_Pos))
1091         {
1092             i32Vddf = (MCUCTRL_LDOREG2_MEMLDOACTIVETRIM_Msk >> MCUCTRL_LDOREG2_MEMLDOACTIVETRIM_Pos);
1093         }
1094 
1095         i32ActualCode = i32Vddf - i32ActualCode;
1096         MCUCTRL->LDOREG2_b.MEMLDOACTIVETRIM = i32Vddf;
1097     }
1098 
1099     am_hal_flash_delay( FLASH_CYCLES_US(20) );
1100     AM_CRITICAL_END;
1101     return i32ActualCode;
1102 }
1103 
1104 //****************************************************************************
1105 //
1106 // Adjust the simobuck vddc/vddf active trim values with saturation.
1107 // Based on default trim setting
1108 // Returns actual adjusted amount of trim code
1109 // (Requires Info1 patch5)
1110 //
1111 //****************************************************************************
1112 int32_t
am_hal_pwrctrl_simobuck_vddx_active_trim_adj_default(am_hal_burst_voltage_wa_e vddx,int32_t vddx_code)1113 am_hal_pwrctrl_simobuck_vddx_active_trim_adj_default(am_hal_burst_voltage_wa_e vddx, int32_t vddx_code)
1114 {
1115     //
1116     // save original SIMOBUCK1 value, it will be restored
1117     //
1118     int32_t i32ActualCode = 0;
1119 
1120     //
1121     // check if info1 patch5 is present
1122     //
1123     if (!am_hal_burst_ldo_patch_check())
1124     {
1125         return 0;
1126     }
1127 
1128     AM_CRITICAL_BEGIN;
1129     if (vddx == AM_HAL_BURST_VDDC)
1130     {
1131         int32_t i32Vddc = simobuck_vddx_default_trim_get(AM_HAL_BURST_VDDC);
1132         i32ActualCode = i32Vddc;
1133         i32Vddc += vddx_code;
1134 
1135         //
1136         // check for overflow and limit
1137         //
1138         if (i32Vddc < 0)
1139         {
1140             i32Vddc = 0;
1141         }
1142         else if (i32Vddc > (MCUCTRL_SIMOBUCK1_COREACTIVETRIM_Msk >> MCUCTRL_SIMOBUCK1_COREACTIVETRIM_Pos))
1143         {
1144             i32Vddc = (MCUCTRL_SIMOBUCK1_COREACTIVETRIM_Msk >> MCUCTRL_SIMOBUCK1_COREACTIVETRIM_Pos);
1145         }
1146 
1147         i32ActualCode = i32Vddc - i32ActualCode;
1148         MCUCTRL->SIMOBUCK1_b.COREACTIVETRIM = i32Vddc;
1149     }
1150     else if (vddx == AM_HAL_BURST_VDDF)
1151     {
1152         int32_t i32Vddf = simobuck_vddx_default_trim_get(AM_HAL_BURST_VDDF);
1153         i32ActualCode = i32Vddf;
1154         i32Vddf += vddx_code;
1155 
1156         //
1157         // check for overflow and limit
1158         //
1159         if (i32Vddf < 0)
1160         {
1161             i32Vddf = 0;
1162         }
1163         else if (i32Vddf > (MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Msk >> MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Pos))
1164         {
1165             i32Vddf = (MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Msk >> MCUCTRL_SIMOBUCK1_MEMACTIVETRIM_Pos);
1166         }
1167 
1168         i32ActualCode = i32Vddf - i32ActualCode;
1169         MCUCTRL->SIMOBUCK1_b.MEMACTIVETRIM = i32Vddf;
1170     }
1171 
1172     am_hal_flash_delay( FLASH_CYCLES_US(20) );
1173     AM_CRITICAL_END;
1174     return i32ActualCode;
1175 }
1176 
1177 //****************************************************************************
1178 //
1179 // Adjust the LDO vddc/vddf active trim values with saturation.
1180 // Based on default trim setting
1181 // (Requires Info1 patch5)
1182 // Returns actual adjusted amount of trim code
1183 //
1184 //****************************************************************************
1185 int32_t
am_hal_pwrctrl_ldo_vddx_active_trim_adj_default(am_hal_burst_voltage_wa_e vddx,int32_t vddx_code)1186 am_hal_pwrctrl_ldo_vddx_active_trim_adj_default(am_hal_burst_voltage_wa_e vddx, int32_t vddx_code)
1187 {
1188     //
1189     // save original LDO value, it will be restored
1190     //
1191     int32_t i32ActualCode = 0;
1192 
1193     //
1194     // check if info1 patch5 is present
1195     //
1196     if (!am_hal_burst_ldo_patch_check())
1197     {
1198         return 0;
1199     }
1200 
1201     AM_CRITICAL_BEGIN;
1202     if (vddx == AM_HAL_BURST_VDDC)
1203     {
1204         int32_t i32Vddc = ldo_vddx_default_trim_get(AM_HAL_BURST_VDDC);
1205         i32ActualCode = i32Vddc;
1206         i32Vddc += vddx_code;
1207 
1208         //
1209         // check for overflow and limit
1210         //
1211         if (i32Vddc < 0)
1212         {
1213             i32Vddc = 0;
1214         }
1215         else if (i32Vddc > (MCUCTRL_LDOREG1_CORELDOACTIVETRIM_Msk >> MCUCTRL_LDOREG1_CORELDOACTIVETRIM_Pos))
1216         {
1217             i32Vddc = (MCUCTRL_LDOREG1_CORELDOACTIVETRIM_Msk >> MCUCTRL_LDOREG1_CORELDOACTIVETRIM_Pos);
1218         }
1219 
1220         i32ActualCode = i32Vddc - i32ActualCode;
1221         MCUCTRL->LDOREG1_b.CORELDOACTIVETRIM = i32Vddc;
1222     }
1223     else if (vddx == AM_HAL_BURST_VDDF)
1224     {
1225         int32_t i32Vddf = ldo_vddx_default_trim_get(AM_HAL_BURST_VDDF);
1226         i32ActualCode = i32Vddf;
1227         i32Vddf += vddx_code;
1228 
1229         //
1230         // check for overflow and limit
1231         //
1232         if (i32Vddf < 0)
1233         {
1234             i32Vddf = 0;
1235         }
1236         else if (i32Vddf > (MCUCTRL_LDOREG2_MEMLDOACTIVETRIM_Msk >> MCUCTRL_LDOREG2_MEMLDOACTIVETRIM_Pos))
1237         {
1238             i32Vddf = (MCUCTRL_LDOREG2_MEMLDOACTIVETRIM_Msk >> MCUCTRL_LDOREG2_MEMLDOACTIVETRIM_Pos);
1239         }
1240 
1241         i32ActualCode = i32Vddf - i32ActualCode;
1242         MCUCTRL->LDOREG2_b.MEMLDOACTIVETRIM = i32Vddf;
1243     }
1244 
1245     am_hal_flash_delay( FLASH_CYCLES_US(20) );
1246     AM_CRITICAL_END;
1247     return i32ActualCode;
1248 }
1249 
1250 //****************************************************************************
1251 //
1252 //  Boost VDDF if CV Patch applied
1253 //
1254 //****************************************************************************
1255 void
am_hal_pwrctrl_wa_vddf_boost(void)1256 am_hal_pwrctrl_wa_vddf_boost(void)
1257 {
1258     //
1259     // Boost VDDF value
1260     //
1261     AM_CRITICAL_BEGIN
1262     if (PWRCTRL->MISC_b.SIMOBUCKEN == 1)
1263     {
1264         am_hal_pwrctrl_simobuck_vddx_active_trim_adj_default(AM_HAL_BURST_VDDF, AM_HAL_BURST_BUCK_VDDF_ADJ_CODE_30MV);
1265     }
1266     else
1267     {
1268         am_hal_pwrctrl_ldo_vddx_active_trim_adj_default(AM_HAL_BURST_VDDF, AM_HAL_BURST_LDO_VDDF_ADJ_CODE_30MV);
1269     }
1270     am_hal_flash_delay( FLASH_CYCLES_US(20) );
1271     AM_CRITICAL_END
1272 }
1273 
1274 //****************************************************************************
1275 //
1276 //  Restore VDDF if CV Patch applied
1277 //
1278 //****************************************************************************
1279 void
am_hal_pwrctrl_wa_vddf_restore(void)1280 am_hal_pwrctrl_wa_vddf_restore(void)
1281 {
1282     //
1283     // Restore VDDF value
1284     //
1285     AM_CRITICAL_BEGIN
1286     if (PWRCTRL->MISC_b.SIMOBUCKEN == 1)
1287     {
1288         am_hal_pwrctrl_simobuck_vddx_active_trim_adj_default(AM_HAL_BURST_VDDF, 0);
1289     }
1290     else
1291     {
1292         am_hal_pwrctrl_ldo_vddx_active_trim_adj_default(AM_HAL_BURST_VDDF, 0);
1293     }
1294     am_hal_flash_delay( FLASH_CYCLES_US(20) );
1295     AM_CRITICAL_END
1296 }
1297 
1298 #endif // AM_HAL_BURST_LDO_WORKAROUND
1299 
1300 //*****************************************************************************
1301 //
1302 // End Doxygen group.
1303 //! @}
1304 //
1305 //*****************************************************************************
1306