1 //*****************************************************************************
2 //
3 //! @file am_hal_pwrctrl.c
4 //!
5 //! @brief Functions for enabling and disabling power domains.
6 //!
7 //! @addtogroup pwrctrl3 Pwrctrl - Power Control
8 //! @ingroup apollo3_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 //
70 //    Mask of HCPA Enables from the PWRCTRL->DEVPWRSTATUS register mapped to the
71 //        PWRCTRL->DEVPWREN register
72 //
73 #define HCPA_MASK       ( \
74     _VAL2FLD(PWRCTRL_DEVPWREN_PWRIOS, PWRCTRL_DEVPWREN_PWRIOS_EN) | \
75     _VAL2FLD(PWRCTRL_DEVPWREN_PWRUART0, PWRCTRL_DEVPWREN_PWRUART0_EN) | \
76     _VAL2FLD(PWRCTRL_DEVPWREN_PWRUART1, PWRCTRL_DEVPWREN_PWRUART1_EN) | \
77     _VAL2FLD(PWRCTRL_DEVPWREN_PWRSCARD, PWRCTRL_DEVPWREN_PWRSCARD_EN))
78 
79 //
80 //    Mask of HCPB Enables from the PWRCTRL->DEVPWRSTATUS register mapped to the
81 //        PWRCTRL->DEVPWREN register
82 //
83 #define HCPB_MASK       ( \
84     _VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM0, PWRCTRL_DEVPWREN_PWRIOM0_EN) | \
85     _VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM1, PWRCTRL_DEVPWREN_PWRIOM1_EN) | \
86     _VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM2, PWRCTRL_DEVPWREN_PWRIOM2_EN))
87 
88 //
89 //    Mask of HCPC Enables from the PWRCTRL->DEVPWRSTATUS register mapped to the
90 //        PWRCTRL->DEVPWREN register
91 //
92 #define HCPC_MASK       ( \
93     _VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM3, PWRCTRL_DEVPWREN_PWRIOM3_EN) | \
94     _VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM4, PWRCTRL_DEVPWREN_PWRIOM4_EN) | \
95     _VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM5, PWRCTRL_DEVPWREN_PWRIOM5_EN))
96 
97 //
98 // Define the peripheral control structure.
99 //
100 const struct
101 {
102     uint32_t      ui32PeriphEnable;
103     uint32_t      ui32PeriphStatus;
104     uint32_t      ui32PeriphEvent;
105 }
106 
107 am_hal_pwrctrl_peripheral_control[AM_HAL_PWRCTRL_PERIPH_MAX] =
108 {
109     {0, 0, 0},                                  //  AM_HAL_PWRCTRL_PERIPH_NONE
110     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRIOS, PWRCTRL_DEVPWREN_PWRIOS_EN),
111      PWRCTRL_DEVPWRSTATUS_HCPA_Msk,
112      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPAEVEN, PWRCTRL_DEVPWREVENTEN_HCPAEVEN_EN)},  // AM_HAL_PWRCTRL_PERIPH_IOS
113     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM0, PWRCTRL_DEVPWREN_PWRIOM0_EN),
114      PWRCTRL_DEVPWRSTATUS_HCPB_Msk,
115      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPBEVEN, PWRCTRL_DEVPWREVENTEN_HCPBEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_IOM0
116     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM1, PWRCTRL_DEVPWREN_PWRIOM1_EN),
117      PWRCTRL_DEVPWRSTATUS_HCPB_Msk,
118      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPBEVEN, PWRCTRL_DEVPWREVENTEN_HCPBEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_IOM1
119     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM2, PWRCTRL_DEVPWREN_PWRIOM2_EN),
120      PWRCTRL_DEVPWRSTATUS_HCPB_Msk,
121      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPBEVEN, PWRCTRL_DEVPWREVENTEN_HCPBEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_IOM2
122     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM3, PWRCTRL_DEVPWREN_PWRIOM3_EN),
123      PWRCTRL_DEVPWRSTATUS_HCPC_Msk,
124      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPCEVEN, PWRCTRL_DEVPWREVENTEN_HCPCEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_IOM3
125     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM4, PWRCTRL_DEVPWREN_PWRIOM4_EN),
126      PWRCTRL_DEVPWRSTATUS_HCPC_Msk,
127      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPCEVEN, PWRCTRL_DEVPWREVENTEN_HCPCEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_IOM4
128     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRIOM5, PWRCTRL_DEVPWREN_PWRIOM5_EN),
129      PWRCTRL_DEVPWRSTATUS_HCPC_Msk,
130      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPCEVEN, PWRCTRL_DEVPWREVENTEN_HCPCEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_IOM5
131     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRUART0, PWRCTRL_DEVPWREN_PWRUART0_EN),
132      PWRCTRL_DEVPWRSTATUS_HCPA_Msk,
133      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPAEVEN, PWRCTRL_DEVPWREVENTEN_HCPAEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_UART0
134     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRUART1, PWRCTRL_DEVPWREN_PWRUART1_EN),
135      PWRCTRL_DEVPWRSTATUS_HCPA_Msk,
136      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPAEVEN, PWRCTRL_DEVPWREVENTEN_HCPAEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_UART1
137     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRADC, PWRCTRL_DEVPWREN_PWRADC_EN),
138      PWRCTRL_DEVPWRSTATUS_PWRADC_Msk,
139      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_ADCEVEN, PWRCTRL_DEVPWREVENTEN_ADCEVEN_EN)},    //  AM_HAL_PWRCTRL_PERIPH_ADC
140     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRSCARD, PWRCTRL_DEVPWREN_PWRSCARD_EN),
141      PWRCTRL_DEVPWRSTATUS_HCPA_Msk,
142      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_HCPAEVEN, PWRCTRL_DEVPWREVENTEN_HCPAEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_SCARD
143     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRMSPI, PWRCTRL_DEVPWREN_PWRMSPI_EN),
144      PWRCTRL_DEVPWRSTATUS_PWRMSPI_Msk,
145      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_MSPIEVEN, PWRCTRL_DEVPWREVENTEN_MSPIEVEN_EN)},  //  AM_HAL_PWRCTRL_PERIPH_MSPI
146     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRPDM, PWRCTRL_DEVPWREN_PWRPDM_EN),
147      PWRCTRL_DEVPWRSTATUS_PWRPDM_Msk,
148      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_PDMEVEN, PWRCTRL_DEVPWREVENTEN_PDMEVEN_EN)},    //  AM_HAL_PWRCTRL_PERIPH_PDM
149     {_VAL2FLD(PWRCTRL_DEVPWREN_PWRBLEL, PWRCTRL_DEVPWREN_PWRBLEL_EN),
150      PWRCTRL_DEVPWRSTATUS_BLEL_Msk,
151      _VAL2FLD(PWRCTRL_DEVPWREVENTEN_BLELEVEN, PWRCTRL_DEVPWREVENTEN_BLELEVEN_EN)}   //  AM_HAL_PWRCTRL_PERIPH_BLEL
152 };
153 
154 //
155 // Define the memory control structure.
156 //
157 const struct
158 {
159     uint32_t      ui32MemoryEnable;
160     uint32_t      ui32MemoryStatus;
161     uint32_t      ui32MemoryEvent;
162     uint32_t      ui32MemoryMask;
163     uint32_t      ui32StatusMask;
164     uint32_t      ui32PwdSlpEnable;
165 }
166 
167 am_hal_pwrctrl_memory_control[AM_HAL_PWRCTRL_MEM_MAX] =
168 {
169     {0, 0, 0, 0, 0, 0},
170     {AM_HAL_PWRCTRL_MEMEN_SRAM_8K_DTCM,
171      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_8K_DTCM,
172      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_8K_DTCM,
173      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
174      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
175      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_8K_DTCM},
176     {AM_HAL_PWRCTRL_MEMEN_SRAM_32K_DTCM,
177      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_32K_DTCM,
178      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_32K_DTCM,
179      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
180      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
181      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_32K_DTCM},
182     {AM_HAL_PWRCTRL_MEMEN_SRAM_64K_DTCM,
183      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_64K_DTCM,
184      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_64K_DTCM,
185      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
186      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
187      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_64K_DTCM},
188     {AM_HAL_PWRCTRL_MEMEN_SRAM_96K,
189      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_96K,
190      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_96K,
191      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
192      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
193      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_96K},
194     {AM_HAL_PWRCTRL_MEMEN_SRAM_128K,
195      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_128K,
196      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_128K,
197      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
198      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
199      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_128K},
200     {AM_HAL_PWRCTRL_MEMEN_SRAM_160K,
201      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_160K,
202      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_160K,
203      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
204      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
205      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_160K},
206     {AM_HAL_PWRCTRL_MEMEN_SRAM_192K,
207      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_192K,
208      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_192K,
209      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
210      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
211      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_192K},
212     {AM_HAL_PWRCTRL_MEMEN_SRAM_224K,
213      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_224K,
214      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_224K,
215      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
216      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
217      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_224K},
218     {AM_HAL_PWRCTRL_MEMEN_SRAM_256K,
219      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_256K,
220      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_256K,
221      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
222      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
223      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_256K},
224     {AM_HAL_PWRCTRL_MEMEN_SRAM_288K,
225      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_288K,
226      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_288K,
227      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
228      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
229      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_288K},
230     {AM_HAL_PWRCTRL_MEMEN_SRAM_320K,
231      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_320K,
232      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_320K,
233      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
234      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
235      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_320K},
236     {AM_HAL_PWRCTRL_MEMEN_SRAM_352K,
237      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_352K,
238      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_352K,
239      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
240      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
241      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_352K},
242     {AM_HAL_PWRCTRL_MEMEN_SRAM_384K,
243      AM_HAL_PWRCTRL_PWRONSTATUS_SRAM_384K,
244      AM_HAL_PWRCTRL_MEMPWREVENTEN_SRAM_384K,
245      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
246      AM_HAL_PWRCTRL_MEM_REGION_SRAM_MASK,
247      AM_HAL_PWRCTRL_MEMPWDINSLEEP_SRAM_384K},
248     {AM_HAL_PWRCTRL_MEMEN_FLASH_512K,
249      AM_HAL_PWRCTRL_PWRONSTATUS_FLASH_512K,
250      AM_HAL_PWRCTRL_MEMPWREVENTEN_FLASH_512K,
251      AM_HAL_PWRCTRL_MEM_REGION_FLASH_MASK,
252      AM_HAL_PWRCTRL_MEM_REGION_FLASH_MASK,
253      AM_HAL_PWRCTRL_MEMPWDINSLEEP_FLASH_512K},
254     {AM_HAL_PWRCTRL_MEMEN_FLASH_1M,
255      AM_HAL_PWRCTRL_PWRONSTATUS_FLASH_1M,
256      AM_HAL_PWRCTRL_MEMPWREVENTEN_FLASH_1M,
257      AM_HAL_PWRCTRL_MEM_REGION_FLASH_MASK,
258      AM_HAL_PWRCTRL_MEM_REGION_FLASH_MASK,
259      AM_HAL_PWRCTRL_MEMPWDINSLEEP_FLASH_1M},
260     {AM_HAL_PWRCTRL_MEMEN_CACHE,
261      0,
262      AM_HAL_PWRCTRL_MEMPWREVENTEN_CACHE,
263      AM_HAL_PWRCTRL_MEM_REGION_CACHE_MASK,
264      0,
265      AM_HAL_PWRCTRL_MEMPWDINSLEEP_CACHE},
266     {AM_HAL_PWRCTRL_MEMEN_ALL,
267      AM_HAL_PWRCTRL_PWRONSTATUS_ALL,
268      AM_HAL_PWRCTRL_MEMPWREVENTEN_ALL,
269      AM_HAL_PWRCTRL_MEM_REGION_ALL_MASK,
270      AM_HAL_PWRCTRL_MEM_REGION_ALT_ALL_MASK,
271      AM_HAL_PWRCTRL_MEMPWDINSLEEP_ALL}
272 };
273 
274 // ****************************************************************************
275 //
276 //  am_hal_pwrctrl_periph_enable()
277 //  Enable power for a peripheral.
278 //
279 // ****************************************************************************
280 uint32_t
am_hal_pwrctrl_periph_enable(am_hal_pwrctrl_periph_e ePeripheral)281 am_hal_pwrctrl_periph_enable(am_hal_pwrctrl_periph_e ePeripheral)
282 {
283     //
284     // Enable power control for the given device.
285     //
286     AM_CRITICAL_BEGIN
287     PWRCTRL->DEVPWREN |= am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphEnable;
288     AM_CRITICAL_END
289 
290     for (uint32_t wait_usecs = 0; wait_usecs < AM_HAL_PWRCTRL_MAX_WAIT; wait_usecs += 10)
291     {
292         am_hal_flash_delay(FLASH_CYCLES_US(10));
293 
294         if ((PWRCTRL->DEVPWRSTATUS & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphStatus) > 0)
295         {
296             break;
297         }
298     }
299 
300     //
301     // Check the device status.
302     //
303     if ((PWRCTRL->DEVPWRSTATUS & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphStatus) > 0)
304     {
305         return AM_HAL_STATUS_SUCCESS;
306     }
307     else
308     {
309         //
310         // IF the Power Enable fails, make sure the DEVPWREN is Low
311         //
312         AM_CRITICAL_BEGIN
313         PWRCTRL->DEVPWREN &= ~am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphEnable;
314         AM_CRITICAL_END
315 
316         return AM_HAL_STATUS_FAIL;
317     }
318 } // am_hal_pwrctrl_periph_enable()
319 
320 // ****************************************************************************
321 //
322 //  am_hal_pwrctrl_periph_disable_msk_check()
323 //  Function checks the PWRCTRL->DEVPWREN since the PWRCTRL->DEVPWRSTATUS
324 //        register alone cannot tell the user if a peripheral is enabled when
325 //        and HCPx register is being used.
326 //
327 // ****************************************************************************
328 static uint32_t
pwrctrl_periph_disable_msk_check(am_hal_pwrctrl_periph_e ePeripheral)329 pwrctrl_periph_disable_msk_check(am_hal_pwrctrl_periph_e ePeripheral)
330 {
331     uint32_t retVal = AM_HAL_STATUS_FAIL;
332     uint32_t HCPxMask = PWRCTRL->DEVPWREN;
333 
334     switch (am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphStatus)
335     {
336         case (PWRCTRL_DEVPWRSTATUS_HCPA_Msk):
337             if (((HCPxMask & HCPA_MASK) > 0) && ((HCPxMask & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphEnable) == 0))
338             {
339                 retVal = AM_HAL_STATUS_SUCCESS;
340             }
341             break;
342 
343         case (PWRCTRL_DEVPWRSTATUS_HCPB_Msk):
344             if (((HCPxMask & HCPB_MASK) > 0) && ((HCPxMask & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphEnable) == 0))
345             {
346                 retVal = AM_HAL_STATUS_SUCCESS;
347             }
348             break;
349 
350         case (PWRCTRL_DEVPWRSTATUS_HCPC_Msk):
351             if (((HCPxMask & HCPC_MASK) > 0) && ((HCPxMask & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphEnable) == 0))
352             {
353                 retVal = AM_HAL_STATUS_SUCCESS;
354             }
355             break;
356 
357         default:
358             break;
359     }
360 
361     return retVal;
362 }
363 
364 // ****************************************************************************
365 //
366 //  am_hal_pwrctrl_periph_disable()
367 //  Disable power for a peripheral.
368 //
369 // ****************************************************************************
370 uint32_t
am_hal_pwrctrl_periph_disable(am_hal_pwrctrl_periph_e ePeripheral)371 am_hal_pwrctrl_periph_disable(am_hal_pwrctrl_periph_e ePeripheral)
372 {
373     //
374     // Disable power domain for the given device.
375     //
376     AM_CRITICAL_BEGIN
377     PWRCTRL->DEVPWREN &= ~am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphEnable;
378     AM_CRITICAL_END
379 
380     for (uint32_t wait_usecs = 0; wait_usecs < AM_HAL_PWRCTRL_MAX_WAIT; wait_usecs += 10)
381     {
382         am_hal_flash_delay(FLASH_CYCLES_US(10));
383 
384         if ((PWRCTRL->DEVPWRSTATUS & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphStatus) == 0)
385         {
386             break;
387         }
388     }
389 
390     //
391     // Check the device status.
392     //
393     if ((PWRCTRL->DEVPWRSTATUS & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphStatus) == 0)
394     {
395         return AM_HAL_STATUS_SUCCESS;
396     }
397     else
398     {
399         return pwrctrl_periph_disable_msk_check(ePeripheral);
400     }
401 
402 } // am_hal_pwrctrl_periph_disable()
403 
404 //*****************************************************************************
405 //
406 // am_hal_pwrctrl_periph_enabled()
407 // This function determines to the caller whether a given peripheral is
408 // currently enabled or disabled.
409 //
410 //*****************************************************************************
411 uint32_t
am_hal_pwrctrl_periph_enabled(am_hal_pwrctrl_periph_e ePeripheral,uint32_t * pui32Enabled)412 am_hal_pwrctrl_periph_enabled(am_hal_pwrctrl_periph_e ePeripheral,
413                               uint32_t *pui32Enabled)
414 {
415     uint32_t ui32Mask = am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphStatus;
416     uint32_t ui32Enabled = 0;
417 
418     if (pui32Enabled == NULL)
419     {
420         return AM_HAL_STATUS_INVALID_ARG;
421     }
422 
423     if (ui32Mask != 0)
424     {
425         ui32Enabled = PWRCTRL->DEVPWRSTATUS & ui32Mask ? 1 : 0;
426         ui32Enabled = ui32Enabled && (PWRCTRL->DEVPWREN & am_hal_pwrctrl_peripheral_control[ePeripheral].ui32PeriphEnable);
427     }
428 
429     *pui32Enabled = ui32Enabled;
430 
431     return AM_HAL_STATUS_SUCCESS;
432 
433 } // am_hal_pwrctrl_periph_enabled()
434 
435 // ****************************************************************************
436 //
437 //  am_hal_pwrctrl_memory_enable()
438 //  Enable a configuration of memory.
439 //
440 // ****************************************************************************
441 uint32_t
am_hal_pwrctrl_memory_enable(am_hal_pwrctrl_mem_e eMemConfig)442 am_hal_pwrctrl_memory_enable(am_hal_pwrctrl_mem_e eMemConfig)
443 {
444     uint32_t ui32MemEnMask, ui32MemDisMask, ui32MemRegionMask, ui32MemStatusMask;
445 
446     ui32MemEnMask     =  am_hal_pwrctrl_memory_control[eMemConfig].ui32MemoryEnable;
447     ui32MemDisMask    = ~am_hal_pwrctrl_memory_control[eMemConfig].ui32MemoryEnable;
448     ui32MemRegionMask = am_hal_pwrctrl_memory_control[eMemConfig].ui32MemoryMask;
449     ui32MemStatusMask = am_hal_pwrctrl_memory_control[eMemConfig].ui32StatusMask;
450 
451     //
452     // Disable unneeded memory. If nothing to be disabled, skip to save time.
453     //
454     // Note that a deliberate disable step using a disable mask is taken here
455     // for 2 reasons: 1) To only affect the specified type of memory, and 2)
456     // To avoid inadvertently disabling any memory currently being depended on.
457     //
458     if ( ui32MemDisMask != 0 )
459     {
460         PWRCTRL->MEMPWREN &=
461             ~(ui32MemDisMask & ui32MemRegionMask)                                   |
462              (_VAL2FLD(PWRCTRL_MEMPWREN_DTCM, PWRCTRL_MEMPWREN_DTCM_GROUP0DTCM0)    |
463               _VAL2FLD(PWRCTRL_MEMPWREN_FLASH0, PWRCTRL_MEMPWREN_FLASH0_EN));
464         am_hal_flash_delay(FLASH_CYCLES_US(1));
465     }
466 
467     //
468     // Enable the required memory.
469     //
470     if ( ui32MemEnMask != 0 )
471     {
472         PWRCTRL->MEMPWREN |= ui32MemEnMask;
473 
474         for (uint32_t wait_usecs = 0; wait_usecs < AM_HAL_PWRCTRL_MAX_WAIT; wait_usecs += 10)
475         {
476             am_hal_flash_delay(FLASH_CYCLES_US(10));
477 
478             if ( (PWRCTRL->MEMPWRSTATUS & ui32MemStatusMask) ==
479                   am_hal_pwrctrl_memory_control[eMemConfig].ui32MemoryStatus )
480             {
481                 break;
482             }
483         }
484     }
485 
486     //
487     // Return status based on whether the power control memory status has reached the desired state.
488     //
489     if ( ( PWRCTRL->MEMPWRSTATUS & ui32MemStatusMask) ==
490            am_hal_pwrctrl_memory_control[eMemConfig].ui32MemoryStatus )
491     {
492         return AM_HAL_STATUS_SUCCESS;
493     }
494     else
495     {
496         return AM_HAL_STATUS_FAIL;
497     }
498 
499 } // am_hal_pwrctrl_memory_enable()
500 
501 // ****************************************************************************
502 //
503 //  am_hal_pwrctrl_memory_deepsleep_powerdown()
504 //  Power down respective memory.
505 //
506 // ****************************************************************************
507 uint32_t
am_hal_pwrctrl_memory_deepsleep_powerdown(am_hal_pwrctrl_mem_e eMemConfig)508 am_hal_pwrctrl_memory_deepsleep_powerdown(am_hal_pwrctrl_mem_e eMemConfig)
509 {
510     if ( eMemConfig >= AM_HAL_PWRCTRL_MEM_MAX )
511     {
512         return AM_HAL_STATUS_FAIL;
513     }
514 
515     //
516     // Power down the required memory.
517     //
518     PWRCTRL->MEMPWDINSLEEP |= am_hal_pwrctrl_memory_control[eMemConfig].ui32PwdSlpEnable;
519 
520     return AM_HAL_STATUS_SUCCESS;
521 
522 } // am_hal_pwrctrl_memory_deepsleep_powerdown()
523 
524 // ****************************************************************************
525 //
526 //  am_hal_pwrctrl_memory_deepsleep_retain()
527 //  Apply retention voltage to respective memory.
528 //
529 // ****************************************************************************
530 uint32_t
am_hal_pwrctrl_memory_deepsleep_retain(am_hal_pwrctrl_mem_e eMemConfig)531 am_hal_pwrctrl_memory_deepsleep_retain(am_hal_pwrctrl_mem_e eMemConfig)
532 {
533     if ( eMemConfig >= AM_HAL_PWRCTRL_MEM_MAX )
534     {
535         return AM_HAL_STATUS_FAIL;
536     }
537 
538     //
539     // Retain the required memory.
540     //
541     PWRCTRL->MEMPWDINSLEEP &= ~am_hal_pwrctrl_memory_control[eMemConfig].ui32PwdSlpEnable;
542 
543     return AM_HAL_STATUS_SUCCESS;
544 
545 } // am_hal_pwrctrl_memory_deepsleep_retain()
546 
547 // ****************************************************************************
548 //  simobuck_updates()
549 // ****************************************************************************
550 static void
simobuck_updates(void)551 simobuck_updates(void)
552 {
553     //
554     // Adjust the SIMOBUCK LP settings.
555     //
556     if ( APOLLO3_GE_B0 )
557     {
558         MCUCTRL->SIMOBUCK2_b.SIMOBUCKCORELPHIGHTONTRIM  = 2;
559         MCUCTRL->SIMOBUCK2_b.SIMOBUCKCORELPLOWTONTRIM   = 3;
560         MCUCTRL->SIMOBUCK3_b.SIMOBUCKCORELPHIGHTOFFTRIM = 5;
561         MCUCTRL->SIMOBUCK3_b.SIMOBUCKCORELPLOWTOFFTRIM  = 2;
562         MCUCTRL->SIMOBUCK3_b.SIMOBUCKMEMLPHIGHTOFFTRIM  = 6;
563         MCUCTRL->SIMOBUCK3_b.SIMOBUCKMEMLPLOWTOFFTRIM   = 1;
564         MCUCTRL->SIMOBUCK3_b.SIMOBUCKMEMLPHIGHTONTRIM   = 3;
565         MCUCTRL->SIMOBUCK4_b.SIMOBUCKMEMLPLOWTONTRIM    = 3;
566     }
567 
568     //
569     // Adjust the SIMOBUCK Timeout settings.
570     //
571     if ( APOLLO3_GE_A1 )
572     {
573         MCUCTRL->SIMOBUCK4_b.SIMOBUCKCOMP2TIMEOUTEN = 0;
574     }
575 
576 } // simobuck_updates()
577 
578 // ****************************************************************************
579 //
580 //  am_hal_pwrctrl_low_power_init()
581 //  Initialize system for low power configuration.
582 //
583 // ****************************************************************************
584 uint32_t
am_hal_pwrctrl_low_power_init(void)585 am_hal_pwrctrl_low_power_init(void)
586 {
587     uint32_t      ui32Status;
588 
589     //
590     // Take a snapshot of the reset status, if not done already
591     //
592     if ( !gAmHalResetStatus )
593     {
594         gAmHalResetStatus = RSTGEN->STAT;
595     }
596 
597     //
598     // Software workaround for Errata ERR019.
599     //
600     if ((APOLLO3_A1) && (1 == PWRCTRL->SUPPLYSTATUS_b.SIMOBUCKON))
601     {
602         ui32Status = am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_PDM);
603         if (AM_HAL_STATUS_SUCCESS != ui32Status)
604         {
605             return ui32Status;
606         }
607     }
608 
609     //
610     // Adjust the SIMOBUCK LP settings.
611     //
612     simobuck_updates();
613 
614     //
615     // Configure cache for low power and performance.
616     //
617     am_hal_cachectrl_control(AM_HAL_CACHECTRL_CONTROL_LPMMODE_RECOMMENDED, 0);
618 
619     //
620     // Check if the BLE is already enabled.
621     //
622     if ( PWRCTRL->DEVPWRSTATUS_b.BLEL == 0)
623     {
624         am_hal_pwrctrl_blebuck_trim();
625 
626         //
627         // First request the BLE feature and check that it was available and acknowledged.
628         //
629         MCUCTRL->FEATUREENABLE_b.BLEREQ = 1;
630         ui32Status = am_hal_flash_delay_status_check(10000,
631                         (uint32_t)&MCUCTRL->FEATUREENABLE,
632                         (MCUCTRL_FEATUREENABLE_BLEAVAIL_Msk |
633                          MCUCTRL_FEATUREENABLE_BLEACK_Msk   |
634                          MCUCTRL_FEATUREENABLE_BLEREQ_Msk),
635                         (MCUCTRL_FEATUREENABLE_BLEAVAIL_Msk |
636                          MCUCTRL_FEATUREENABLE_BLEACK_Msk   |
637                          MCUCTRL_FEATUREENABLE_BLEREQ_Msk),
638                          true);
639 
640         if (AM_HAL_STATUS_SUCCESS != ui32Status)
641         {
642             return AM_HAL_STATUS_TIMEOUT;
643         }
644 
645         //
646         // Next, enable the BLE Buck.
647         //
648         PWRCTRL->SUPPLYSRC |= _VAL2FLD(PWRCTRL_SUPPLYSRC_BLEBUCKEN,
649                                        PWRCTRL_SUPPLYSRC_BLEBUCKEN_EN);
650 
651         //
652         // Allow the buck to go to low power mode in BLE sleep.
653         //
654         PWRCTRL->MISC |= _VAL2FLD(PWRCTRL_MISC_MEMVRLPBLE,
655                                   PWRCTRL_MISC_MEMVRLPBLE_EN);
656 
657         //
658         // Check for Apollo3 A0 Silicon.
659         //
660         if ( APOLLO3_A0 )
661         {
662             // Disable SIMO Buck clkdiv because if ble is out of reset then the same bit divides the simobuck clk too aggressively.
663             MCUCTRL->SIMOBUCK4_b.SIMOBUCKCLKDIVSEL = 0x0;
664             MCUCTRL->BLEBUCK2_b.BLEBUCKTONHITRIM   = 0xF;
665             MCUCTRL->BLEBUCK2_b.BLEBUCKTONLOWTRIM  = 0xF;
666         }
667     }
668 
669     return AM_HAL_STATUS_SUCCESS;
670 } // am_hal_pwrctrl_low_power_init()
671 
672 // ****************************************************************************
673 //
674 //  am_hal_pwrctrl_blebuck_trim()
675 //
676 // ****************************************************************************
am_hal_pwrctrl_blebuck_trim(void)677 void am_hal_pwrctrl_blebuck_trim(void)
678 {
679   //
680   // Enable the BLE buck trim values
681   //
682   if ( APOLLO3_GE_A1 )
683   {
684     AM_CRITICAL_BEGIN
685     MCUCTRL->BLEBUCK2_b.BLEBUCKTONHITRIM = 0x19;
686     MCUCTRL->BLEBUCK2_b.BLEBUCKTONLOWTRIM = 0xC;
687     CLKGEN->BLEBUCKTONADJ_b.TONADJUSTEN = CLKGEN_BLEBUCKTONADJ_TONADJUSTEN_DIS;
688     AM_CRITICAL_END
689   }
690 } // am_hal_pwrctrl_blebuck_trim()
691 
692 //*****************************************************************************
693 //
694 // End Doxygen group.
695 //! @}
696 //
697 //*****************************************************************************
698