1 //*****************************************************************************
2 //
3 //! @file am_hal_mcuctrl.c
4 //!
5 //! @brief Functions for interfacing with the MCUCTRL.
6 //!
7 //! @addtogroup mcuctrl4_4p MCUCTRL - MCU 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 
48 #include "am_hal_mcuctrl.h"
49 
50 //*****************************************************************************
51 //
52 // Global Variables.
53 //
54 //*****************************************************************************
55 //
56 //! Lookup table for memory sizes as derived from the SKU register.
57 //!  0: MRAM    size in KB
58 //!  1: TCM     size in KB
59 //!  2: SSRAM   size in KB
60 //!  3: Ext RAM size in KB
61 //
62 static const uint16_t
63 g_am_hal_mcuctrl_sku_ssram_size[AM_HAL_MCUCTRL_SKU_SSRAM_SIZE_N][2] =
64 {
65     {1024, 384},    //! 0x0:  1024KB SRAM + 384KB Ext
66     {2048, 384},    //! 0x1:  2948KB SRAM + 384KB Ext
67     {1024, 384},    //! 0x2:  1024KB SRAM + 384KB Ext
68     {2048, 384}     //! 0x3:  2948KB SRAM + 384KB Ext
69 };
70 
71 //
72 //! Lookup table for MRAM sizes as derived from the SKU register.
73 //
74 static const uint16_t
75 g_am_hal_mcuctrl_sku_mram_size[AM_HAL_MCUCTRL_SKU_MRAM_SIZE_N] =
76 {
77      512,
78      1024,
79      1536,
80      2048
81 };
82 
83 // ****************************************************************************
84 // MCUCTRL XTALHSCAP Globals for Cooper Device
85 // Refer to App Note Apollo4 Blue 32MHz Crystal Calibration
86 // ****************************************************************************
87 uint32_t g_ui32xtalhscap2trim = XTALHSCAP2TRIM_DEFAULT;
88 uint32_t g_ui32xtalhscaptrim = XTALHSCAPTRIM_DEFAULT;
89 
90 //
91 //! These data keeps track of number of users of the HF XTAL CLOCK
92 //! and the HFXTAL padout (HFXTAL clockout)
93 //! when these values are non-zero the respective settings
94 //! (HFXTAL clock, and HFXTAL padout, cannot be disabled)
95 //! the bits in these are set for each user module according to enum
96 //! am_hal_mcuctrl_hfxtal_users_e
97 //
98 typedef struct
99 {
100     uint32_t  g_ui32HfXtalEnFlags;
101     uint32_t  g_ui32HfXtalClockOutlags;
102     bool      b_HfXtalKickStartEnabled;
103 }
104 am_hal_xtal_users_t;
105 
106 am_hal_xtal_users_t am_hal_xtal_users  =
107 {
108     .g_ui32HfXtalEnFlags = 0,
109     .b_HfXtalKickStartEnabled = 0
110 };
111 
112 //
113 //! @brief default stuct used track modifications of XTAL clock behavior
114 //! default structure passed as arg (pointer) into am_hal_mcuctrl_control
115 //! is's assumed the user will change the value of AM_HAL_HCXTAL_DEFAULT_EN
116 //! to module name the user needs the XTAL clock
117 //
118 const am_hal_mcuctrl_control_arg_t g_amHalMcuctrlArgDefault =
119 {
120     .ui32_arg_hfxtal_user_mask = 1 << AM_HAL_HCXTAL_DEFAULT_EN,
121     .b_arg_hfxtal_in_use       = true,
122     .b_arg_apply_ext_source    = false,
123     .b_arg_force_update        = false,
124     .b_arg_enable_HfXtalClockout = false,
125 };
126 //
127 //! default stuct used track modifications of XTAL for BLE
128 //! this was needed in so many places a separate entry has been created
129 //! for this. Additionally BLE will need the 32Mhz (HFXTAL) clockout enabled
130 //
131 const am_hal_mcuctrl_control_arg_t g_amHalMcuctrlArgBLEDefault =
132 {
133     .ui32_arg_hfxtal_user_mask = 1 << AM_HAL_HFXTAL_BLE_CONTROLLER_EN,
134     .b_arg_hfxtal_in_use       = true,
135     .b_arg_apply_ext_source    = false,
136     .b_arg_force_update        = false,
137     .b_arg_enable_HfXtalClockout = true,
138 };
139 
140 
141 static uint32_t
142 mcuctrl_HFXTAL_clockOutPad_mask_modify(bool bClockOutEnable, uint32_t ui32ClockEnableMask );
143 static uint32_t
144 mcuctrl_ctrl_HFXTAL_normal(const am_hal_mcuctrl_control_arg_t *peCtrlArg );
145 static uint32_t
146 mcuctrl_ctrl_HFXTAL_kickstart(const am_hal_mcuctrl_control_arg_t *peCtrlArg );
147 static uint32_t
148 mcuctrl_ctrl_HFXTAL_disable(const am_hal_mcuctrl_control_arg_t *peCtrlArg );
149 static uint32_t
150 mcuctrl_HFXTAL_set_mask(bool bSet, uint32_t ui32Mask );
151 
152 // ****************************************************************************
153 //
154 //  device_info_get()
155 //  Gets all relevant device information.
156 //
157 // ****************************************************************************
158 static void
device_info_get(am_hal_mcuctrl_device_t * psDevice)159 device_info_get(am_hal_mcuctrl_device_t *psDevice)
160 {
161     //
162     // Read the Part Number.
163     //
164     psDevice->ui32ChipPN = MCUCTRL->CHIPPN;
165 
166     //
167     // Read the Chip ID0.
168     //
169     psDevice->ui32ChipID0 = MCUCTRL->CHIPID0;
170 
171     //
172     // Read the Chip ID1.
173     //
174     psDevice->ui32ChipID1 = MCUCTRL->CHIPID1;
175 
176     //
177     // Read the Chip Revision.
178     //
179     psDevice->ui32ChipRev = MCUCTRL->CHIPREV;
180 
181     //
182     // Read the Chip VENDOR ID.
183     //
184     psDevice->ui32VendorID = MCUCTRL->VENDORID;
185 
186     //
187     // Read the SKU.
188     //
189     psDevice->ui32SKU = MCUCTRL->SKU;
190 
191     //
192     // Qualified from Part Number.
193     //
194     psDevice->ui32Qualified = 1;
195 
196     //
197     // MRAM size as derived from the SKU register.
198     //
199     psDevice->ui32MRAMSize = g_am_hal_mcuctrl_sku_mram_size[MCUCTRL->SKU_b.SKUMRAMSIZE] * 1024;
200 
201     //
202     // TCM size.
203     //
204     psDevice->ui32DTCMSize = TCM_MAX_SIZE;
205 
206     //
207     // Shared SRAM size as derived from the SKU register.
208     //
209     psDevice->ui32SSRAMSize = (g_am_hal_mcuctrl_sku_ssram_size[MCUCTRL->SKU_b.SKUSRAMSIZE][0] +
210                                g_am_hal_mcuctrl_sku_ssram_size[MCUCTRL->SKU_b.SKUSRAMSIZE][1]) * 1024;
211 
212     //
213     // Now, let's look at the JEDEC info.
214     // The full partnumber is 12 bits total, but is scattered across 2 registers.
215     // Bits [11:8] are 0xE.
216     // Bits [7:4] are 0xE for Apollo, 0xD for Apollo2.
217     // Bits [3:0] are defined differently for Apollo and Apollo2.
218     //   For Apollo, the low nibble is 0x0.
219     //   For Apollo2, the low nibble indicates flash and SRAM size.
220     //
221     psDevice->ui32JedecPN  = JEDEC->PID0_b.PNL8 << 0;
222     psDevice->ui32JedecPN |= JEDEC->PID1_b.PNH4 << 8;
223 
224     //
225     // JEPID is the JEP-106 Manufacturer ID Code, which is assigned to Ambiq as
226     //  0x1B, with parity bit is 0x9B.  It is 8 bits located across 2 registers.
227     //
228     psDevice->ui32JedecJEPID  = JEDEC->PID1_b.JEPIDL << 0;
229     psDevice->ui32JedecJEPID |= JEDEC->PID2_b.JEPIDH << 4;
230 
231     //
232     // CHIPREV is 8 bits located across 2 registers.
233     //
234     psDevice->ui32JedecCHIPREV  = JEDEC->PID2_b.CHIPREVH4 << 4;
235     psDevice->ui32JedecCHIPREV |= JEDEC->PID3_b.CHIPREVL4 << 0;
236 
237     //
238     // Let's get the Coresight ID (32-bits across 4 registers)
239     // For Apollo and Apollo2, it's expected to be 0xB105100D.
240     //
241     psDevice->ui32JedecCID  = JEDEC->CID3_b.CID << 24;
242     psDevice->ui32JedecCID |= JEDEC->CID2_b.CID << 16;
243     psDevice->ui32JedecCID |= JEDEC->CID1_b.CID <<  8;
244     psDevice->ui32JedecCID |= JEDEC->CID0_b.CID <<  0;
245 
246 } // device_info_get()
247 
248 // ****************************************************************************
249 //
250 //  am_hal_mcuctrl_EXTCLK_active()
251 //  return true if any peripheral is using the HSXTAL clock.
252 //
253 // ****************************************************************************
254 /******************************************************************************
255 //   get usage status of HF clock
256 //
257 // return true if one or more users (modules) are using the HF Xtal clock
258 // return false  if the xtal clock is disabled and there are no users
259  *****************************************************************************/
260 bool
am_hal_mcuctrl_EXTCLK_active(void)261 am_hal_mcuctrl_EXTCLK_active(void )
262 {
263     return am_hal_xtal_users.g_ui32HfXtalEnFlags != 0;
264 }
265 
266 //******************************************************************************
267 //
268 //! @brief set or clear bits the xtal users variable
269 //!
270 //! @param bSet  when true will set bits, when false will clear them
271 //! @param ui32Mask  contains bits to set or clear
272 //!
273 //! @return always success
274 //
275 // *****************************************************************************
276 static uint32_t
mcuctrl_HFXTAL_set_mask(bool bSet,uint32_t ui32Mask)277 mcuctrl_HFXTAL_set_mask(bool bSet, uint32_t ui32Mask )
278 {
279     if ( bSet )
280     {
281         am_hal_xtal_users.g_ui32HfXtalEnFlags |= ui32Mask;
282     }
283     else
284     {
285         am_hal_xtal_users.g_ui32HfXtalEnFlags &= ~ui32Mask;
286     }
287     return AM_HAL_STATUS_SUCCESS;
288 }
289 
290 //****************************************************************************
291 //
292 //! @brief enables HF Xtal
293 //!
294 //! @param peCtrlArg  pointer to struct that controls HF Xtal setups
295 //!
296 //! @return standard hal status
297 //
298 //**************************************************************************
299 static uint32_t
mcuctrl_ctrl_HFXTAL_normal(const am_hal_mcuctrl_control_arg_t * peCtrlArg)300 mcuctrl_ctrl_HFXTAL_normal(const am_hal_mcuctrl_control_arg_t *peCtrlArg )
301 {
302     if (peCtrlArg == 0)
303     {
304         //
305         // this is the legacy call and is no longer supported.
306         //
307         return AM_HAL_STATUS_INVALID_ARG;
308     }
309 
310 
311     //
312     // Begin critical section.
313     //
314     AM_CRITICAL_BEGIN
315 
316     //
317     // remember if the hs xtal clock is enabled on entry
318     //
319     bool bHSXTAL_entry_enabled = am_hal_mcuctrl_EXTCLK_active();
320 
321     if (peCtrlArg->b_arg_hfxtal_in_use)
322     {
323         //
324         // set bit(s) in RAM variable that manage HFXTAL clock enablement
325         //
326         mcuctrl_HFXTAL_set_mask(true, peCtrlArg->ui32_arg_hfxtal_user_mask);
327 
328         //
329         // clear or set clock pad-out bit for this peripheral
330         //
331         mcuctrl_HFXTAL_clockOutPad_mask_modify(peCtrlArg->b_arg_enable_HfXtalClockout,
332                                                peCtrlArg->ui32_arg_hfxtal_user_mask);
333     }
334 
335     bool bHSXTAL_enabled  = am_hal_mcuctrl_EXTCLK_active();
336 
337     //
338     // is the HFXTAL transitioning to enabled with this call
339     //
340     bool bEnableHFXTAL    = !bHSXTAL_entry_enabled && bHSXTAL_enabled;
341 
342     //
343     // if the HFXTAL needs to be enabled, and if it isn't already enabled,
344     // the code below will enable the HFXTAL
345     //
346     if (bEnableHFXTAL || peCtrlArg->b_arg_force_update)
347     {
348 
349         uint32_t ui32TrimReg = _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSCAP2TRIM, g_ui32xtalhscap2trim) |
350                   _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSCAPTRIM, g_ui32xtalhscaptrim) |
351                   _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSDRIVETRIM, 3) |
352                   _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSDRIVERSTRENGTH, 0) |
353                   _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSIBIASCOMP2TRIM, 3) |
354                   _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSIBIASCOMPTRIM, 15) |
355                   _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSIBIASTRIM, 127) |
356                   _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSRSTRIM, 0) |
357                   _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSSPARE, 0);
358         MCUCTRL->XTALHSTRIMS = ui32TrimReg;  // ok
359 
360         uint32_t ui32Reg = MCUCTRL->XTALHSCTRL;
361         ui32Reg &= ~(MCUCTRL_XTALHSCTRL_XTALHSCOMPPDNB_Msk |
362                      MCUCTRL_XTALHSCTRL_XTALHSPDNPNIMPROVE_Msk);
363         ui32Reg |= _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSCOMPPDNB, 1) |
364                    _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSPDNPNIMPROVE, 1);
365         MCUCTRL->XTALHSCTRL = ui32Reg;
366 
367         //
368         // Turn on xtalhs_pdnb
369         //
370         ui32Reg |= _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSPDNB, 1);
371         MCUCTRL->XTALHSCTRL = ui32Reg;
372 
373         //
374         // Apply external source
375         //
376         if (peCtrlArg->b_arg_apply_ext_source)
377         {
378             ui32Reg &= ~(MCUCTRL_XTALHSCTRL_XTALHSPDNB_Msk |
379                          MCUCTRL_XTALHSCTRL_XTALHSEXTERNALCLOCK_Msk);
380             ui32Reg |= _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSPDNB, 0) |
381                        _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSEXTERNALCLOCK, 1);
382         }
383         else
384         {
385             ui32Reg &= ~(MCUCTRL_XTALHSCTRL_XTALHSPDNPNIMPROVE_Msk |
386                          MCUCTRL_XTALHSCTRL_XTALHSIBSTENABLE_Msk);
387             ui32Reg |= _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSPDNPNIMPROVE, 0) |
388                        _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSIBSTENABLE, 1);
389         }
390         MCUCTRL->XTALHSCTRL = ui32Reg;
391 
392     } // not enabled
393 
394     //
395     // End critical section.
396     //
397     AM_CRITICAL_END
398 
399     return AM_HAL_STATUS_SUCCESS;
400 
401 }
402 
403 //******************************************************************************
404 //! @brief enables HF Xtal with kickstart
405 //!
406 //! @param peCtrlArg  pointer to struct that controls HF Xtal setups
407 //!
408 //! @return standard hal status
409 //
410 //*****************************************************************************
411 static uint32_t
mcuctrl_ctrl_HFXTAL_kickstart(const am_hal_mcuctrl_control_arg_t * peCtrlArg)412 mcuctrl_ctrl_HFXTAL_kickstart(const am_hal_mcuctrl_control_arg_t *peCtrlArg )
413 {
414 
415     if (peCtrlArg == 0)
416     {
417         //
418         // this is the legacy call and is no longer supported.
419         //
420         return AM_HAL_STATUS_INVALID_ARG;
421     }
422 
423     //
424     // Begin critical section.
425     //
426     AM_CRITICAL_BEGIN
427 
428     //
429     // remember if the hs xtal clock is enabled on entry
430     //
431     bool bHSXTAL_entry_enabled = am_hal_mcuctrl_EXTCLK_active();
432 
433     if (peCtrlArg->b_arg_hfxtal_in_use)
434     {
435 
436         //
437         // set bit(s) in RAM variable that monitor HFXTAL clock enablement
438         //
439         mcuctrl_HFXTAL_set_mask(true, peCtrlArg->ui32_arg_hfxtal_user_mask);
440 
441         //
442         // clear or set clock pad-out bit for this peripheral
443         //
444         mcuctrl_HFXTAL_clockOutPad_mask_modify(peCtrlArg->b_arg_enable_HfXtalClockout,
445                                                peCtrlArg->ui32_arg_hfxtal_user_mask);
446     }
447 
448     bool bHSXTAL_enabled  = am_hal_mcuctrl_EXTCLK_active();
449 
450     //
451     // is the HFXTAL transitioning to enabled with this call
452     //
453     bool bEnableHFXTAL    = !bHSXTAL_entry_enabled && bHSXTAL_enabled;
454 
455     //
456     // if the HFXTAL needs to be enabled, and if it isn't already enabled,
457     // the code below will enable the HFXTAL
458     //
459     if ( bEnableHFXTAL || peCtrlArg->b_arg_force_update )
460     {
461         am_hal_xtal_users.b_HfXtalKickStartEnabled = true;
462 
463         // Set the default trim code for CAP1/CAP2, it impacts frequency accuracy and should be retrimmed
464         uint32_t ui32TrimReg =
465             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSCAP2TRIM, g_ui32xtalhscap2trim) |
466             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSCAPTRIM, g_ui32xtalhscaptrim) |
467             // Set the transconductance of crystal to maximum, it accelerates the startup sequence
468             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSDRIVETRIM, 3) |
469             // Choose the power of clock driver to be the cleanest one
470             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSDRIVERSTRENGTH, 0) |
471             // Tune the bias generator
472             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSIBIASCOMP2TRIM, 3) |
473             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSIBIASCOMPTRIM, 15) |
474             // Set the bias of crystal to maximum
475             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSIBIASTRIM, 127) |
476             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSRSTRIM, 0) |
477             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSSPARE, 0);
478 
479         MCUCTRL->XTALHSTRIMS = ui32TrimReg;
480 
481         uint32_t ui32Reg = MCUCTRL->XTALHSCTRL;
482         ui32Reg &= ~(MCUCTRL_XTALHSCTRL_XTALHSCOMPPDNB_Msk |
483                      MCUCTRL_XTALHSCTRL_XTALHSPDNPNIMPROVE_Msk);
484         ui32Reg |= _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSCOMPPDNB, 1) |
485                    _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSPDNPNIMPROVE, 0);
486         MCUCTRL->XTALHSCTRL = ui32Reg;
487 
488         //
489         // turn on crystal oscillator
490         //
491         ui32Reg |= _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSPDNB, 1);
492         MCUCTRL->XTALHSCTRL = ui32Reg;
493 
494         //
495         // inject HFRC clock to accelerate the startup sequence
496         //
497         ui32Reg |= _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSINJECTIONENABLE, 1);
498         MCUCTRL->XTALHSCTRL = ui32Reg;
499 
500         //
501         // Turn on xtalhs_ibst_enable
502         //  Maximize the bias current to accelerate the startup sequence
503         //
504         ui32Reg |= _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSIBSTENABLE, 1);
505         MCUCTRL->XTALHSCTRL = ui32Reg;
506 
507         //
508         // Wait 5us to make the setting above effective
509         // Turn off xtalhs_injection_enable (clock injection)
510         //
511         am_hal_delay_us(5);
512 
513 
514         ui32Reg = MCUCTRL->XTALHSCTRL ;
515         ui32Reg &= ~MCUCTRL_XTALHSCTRL_XTALHSINJECTIONENABLE_Msk;
516 
517         if (peCtrlArg->b_arg_apply_ext_source)
518         {
519             ui32Reg &= ~(MCUCTRL_XTALHSCTRL_XTALHSPDNB_Msk |
520                          MCUCTRL_XTALHSCTRL_XTALHSIBSTENABLE_Msk |
521                          MCUCTRL_XTALHSCTRL_XTALHSEXTERNALCLOCK_Msk);
522             ui32Reg |= _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSPDNB, 0) |
523                        _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSIBSTENABLE, 0) |
524                        _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSEXTERNALCLOCK, 1);
525         }
526 
527         MCUCTRL->XTALHSCTRL = ui32Reg;
528 
529 
530     } // !bEnableHFXTAL || peCtrlArg->b_arg_force_update
531 
532     //
533     // End critical section.
534     //
535     AM_CRITICAL_END
536 
537     return AM_HAL_STATUS_SUCCESS;
538 }
539 
540 /******************************************************************************
541 //! @brief sets or clears the clockoutput pin
542 //!
543 //! @note if using preemptive os, this should be called from a critical section
544 //!
545 //! @details clockout is disabled once no no user is requesting it
546 //!
547 //! @param bClockOutEnable  when true clock out is enabled, false it is disabled
548 //! @param ui32ClockEnableMask indicates which user is making this request
549 //!
550 //! @return always success
551  *****************************************************************************/
552 static uint32_t
mcuctrl_HFXTAL_clockOutPad_mask_modify(bool bClockOutEnable,uint32_t ui32ClockEnableMask)553 mcuctrl_HFXTAL_clockOutPad_mask_modify(bool bClockOutEnable, uint32_t ui32ClockEnableMask )
554 {
555     if (bClockOutEnable)
556     {
557         //
558         // Enable the option to output clock on PAD GPIO46
559         // connecting to Cooper crystal input
560         //
561         am_hal_xtal_users.g_ui32HfXtalClockOutlags |= ui32ClockEnableMask;
562     }
563     else
564     {
565         //
566         // Disable clockout on PAD GPIO46
567         //
568         am_hal_xtal_users.g_ui32HfXtalClockOutlags &= ~ui32ClockEnableMask;
569     }
570 
571     //
572     // below the actual register bit is set or cleared
573     //
574     if ( am_hal_xtal_users.g_ui32HfXtalClockOutlags )
575     {
576         MCUCTRL->XTALHSCTRL_b.XTALHSPADOUTEN = 1;
577     }
578     else
579     {
580         MCUCTRL->XTALHSCTRL_b.XTALHSPADOUTEN = 0;
581     }
582 
583     return AM_HAL_STATUS_SUCCESS;
584 }
585 
586 //****************************************************************************
587 //
588 //! @brief disable the HF Xtal clock when it isn't being used
589 //!
590 //! @param peCtrlArg  pointer to struct that controls HF Xtal setups
591 //!
592 //! @return always success
593 //
594 //*****************************************************************************
595 static uint32_t
mcuctrl_ctrl_HFXTAL_disable(const am_hal_mcuctrl_control_arg_t * peCtrlArg)596 mcuctrl_ctrl_HFXTAL_disable(const am_hal_mcuctrl_control_arg_t *peCtrlArg )
597 {
598     if (peCtrlArg == 0)
599     {
600         //
601         // this is the legacy call and is no longer supported.
602         //
603         return AM_HAL_STATUS_INVALID_ARG;
604     }
605 
606     //
607     // Begin critical section.
608     //
609     AM_CRITICAL_BEGIN
610 
611     if (peCtrlArg->b_arg_hfxtal_in_use)
612     {
613 
614         //
615         // clear bit for this peripheral
616         //
617         mcuctrl_HFXTAL_set_mask(false, peCtrlArg->ui32_arg_hfxtal_user_mask);
618 
619         //
620         // clear or set clock pad-out bit for this peripheral
621         //
622         mcuctrl_HFXTAL_clockOutPad_mask_modify(peCtrlArg->b_arg_enable_HfXtalClockout,
623                                                peCtrlArg->ui32_arg_hfxtal_user_mask);
624     }
625 
626     //
627     // don't disable clock until all peripherals have released it
628     // or the action is forced
629     //
630     bool HSXTAL_enabled = am_hal_mcuctrl_EXTCLK_active();
631 
632     if (!HSXTAL_enabled || peCtrlArg->b_arg_force_update)
633     {
634         am_hal_xtal_users.b_HfXtalKickStartEnabled = false;
635 
636         //
637         // clear all bits here, in case b_arg_force_update was used
638         //
639         mcuctrl_HFXTAL_set_mask(false, 0xFFFFFFFF);
640 
641         uint32_t ui32TrimReg  =
642             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSCAP2TRIM, g_ui32xtalhscap2trim)    |
643             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSCAPTRIM, g_ui32xtalhscaptrim)      |
644             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSDRIVETRIM, 0)                      |
645             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSDRIVERSTRENGTH, 7)                 |
646             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSIBIASCOMP2TRIM, 3)                 |
647             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSIBIASCOMPTRIM, 8)                  |
648             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSIBIASTRIM, 24)                     |
649             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSRSTRIM, 0)                         |
650             _VAL2FLD(MCUCTRL_XTALHSTRIMS_XTALHSSPARE, 0);
651         MCUCTRL->XTALHSTRIMS = ui32TrimReg;
652 
653         uint32_t ui32Reg = MCUCTRL->XTALHSCTRL;
654         ui32Reg &= ~(MCUCTRL_XTALHSCTRL_XTALHSPDNB_Msk |
655                      MCUCTRL_XTALHSCTRL_XTALHSEXTERNALCLOCK_Msk |
656                      MCUCTRL_XTALHSCTRL_XTALHSCOMPPDNB_Msk |
657                      MCUCTRL_XTALHSCTRL_XTALHSIBSTENABLE_Msk |
658                      MCUCTRL_XTALHSCTRL_XTALHSPDNPNIMPROVE_Msk);
659 
660         ui32Reg |= _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSPDNB, 0) |
661                    _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSEXTERNALCLOCK, 0) |
662                    _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSCOMPPDNB, 1) |
663                    _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSIBSTENABLE, 0) |
664                    _VAL2FLD(MCUCTRL_XTALHSCTRL_XTALHSPDNPNIMPROVE, 0);
665         MCUCTRL->XTALHSCTRL = ui32Reg;
666     }
667 
668     //
669     // End critical section.
670     //
671     AM_CRITICAL_END
672 
673     return AM_HAL_STATUS_SUCCESS;
674 }
675 
676 
677 // ****************************************************************************
678 //
679 //  am_hal_mcuctrl_control()
680 //  Apply various specific commands/controls on the MCUCTRL module.
681 //
682 // ****************************************************************************
683 uint32_t
am_hal_mcuctrl_control(am_hal_mcuctrl_control_e eControl,void * pArgs)684 am_hal_mcuctrl_control(am_hal_mcuctrl_control_e eControl, void *pArgs)
685 {
686     volatile uint32_t ui32Reg;
687 
688     switch ( eControl )
689     {
690         case AM_HAL_MCUCTRL_CONTROL_EXTCLK32K_ENABLE:
691             //
692             // Configure the bits in XTALCTRL that enable external 32KHz clock.
693             //
694 
695             //
696             // Begin critical section.
697             //
698             AM_CRITICAL_BEGIN
699 
700             ui32Reg  = MCUCTRL->XTALCTRL;
701             ui32Reg &= ~(MCUCTRL_XTALCTRL_XTALPDNB_Msk                      |
702                          MCUCTRL_XTALCTRL_XTALCOMPPDNB_Msk                  |
703                          MCUCTRL_XTALCTRL_XTALCOMPBYPASS_Msk                |
704                          MCUCTRL_XTALCTRL_XTALCOREDISFB_Msk                 |
705                          MCUCTRL_XTALCTRL_XTALSWE_Msk);
706             ui32Reg |= _VAL2FLD(MCUCTRL_XTALCTRL_XTALPDNB,       MCUCTRL_XTALCTRL_XTALPDNB_PWRUPCORE)       |
707                        _VAL2FLD(MCUCTRL_XTALCTRL_XTALCOMPPDNB,   MCUCTRL_XTALCTRL_XTALCOMPPDNB_PWRUPCOMP)   |
708                        _VAL2FLD(MCUCTRL_XTALCTRL_XTALCOMPBYPASS, MCUCTRL_XTALCTRL_XTALCOMPBYPASS_USECOMP)   |
709                        _VAL2FLD(MCUCTRL_XTALCTRL_XTALCOREDISFB,  MCUCTRL_XTALCTRL_XTALCOREDISFB_EN)         |
710                        _VAL2FLD(MCUCTRL_XTALCTRL_XTALSWE,        MCUCTRL_XTALCTRL_XTALSWE_OVERRIDE_EN);
711             MCUCTRL->XTALCTRL = ui32Reg;
712 
713             //
714             // End critical section.
715             //
716             AM_CRITICAL_END
717             break;
718 
719         case AM_HAL_MCUCTRL_CONTROL_EXTCLK32K_DISABLE:
720             //
721             // Configure the bits in XTALCTRL that disable external 32KHz
722             // clock, thus re-configuring for the crystal.
723 
724             //
725             // Begin critical section.
726             //
727             AM_CRITICAL_BEGIN
728 
729             ui32Reg  = MCUCTRL->XTALCTRL;
730             ui32Reg &= ~(MCUCTRL_XTALCTRL_XTALPDNB_Msk                      |
731                          MCUCTRL_XTALCTRL_XTALCOMPPDNB_Msk                  |
732                          MCUCTRL_XTALCTRL_XTALCOMPBYPASS_Msk                |
733                          MCUCTRL_XTALCTRL_XTALCOREDISFB_Msk                 |
734                          MCUCTRL_XTALCTRL_XTALSWE_Msk);
735             ui32Reg |= _VAL2FLD(MCUCTRL_XTALCTRL_XTALPDNB,       MCUCTRL_XTALCTRL_XTALPDNB_PWRUPCORE)       |
736                        _VAL2FLD(MCUCTRL_XTALCTRL_XTALCOMPPDNB,   MCUCTRL_XTALCTRL_XTALCOMPPDNB_PWRUPCOMP)   |
737                        _VAL2FLD(MCUCTRL_XTALCTRL_XTALCOMPBYPASS, MCUCTRL_XTALCTRL_XTALCOMPBYPASS_USECOMP)   |
738                        _VAL2FLD(MCUCTRL_XTALCTRL_XTALCOREDISFB,  MCUCTRL_XTALCTRL_XTALCOREDISFB_EN)         |
739                        _VAL2FLD(MCUCTRL_XTALCTRL_XTALSWE,        MCUCTRL_XTALCTRL_XTALSWE_OVERRIDE_DIS);
740             MCUCTRL->XTALCTRL = ui32Reg;
741 
742             //
743             // End critical section.
744             //
745             AM_CRITICAL_END
746             break;
747         case AM_HAL_MCUCTRL_CONTROL_EXTCLK32M_CLOCKOUT:
748 
749             if ( 0 == pArgs )
750             {
751                 return AM_HAL_STATUS_INVALID_ARG;
752             }
753             return mcuctrl_HFXTAL_clockOutPad_mask_modify(*((bool *) pArgs), (1 << AM_HAL_HCXTAL_DEFAULT_EN));
754 
755         case AM_HAL_MCUCTRL_CONTROL_EXTCLK32M_KICK_START:
756             return mcuctrl_ctrl_HFXTAL_kickstart((am_hal_mcuctrl_control_arg_t *) pArgs);
757 
758         case AM_HAL_MCUCTRL_CONTROL_EXTCLK32M_NORMAL:
759             return mcuctrl_ctrl_HFXTAL_normal((am_hal_mcuctrl_control_arg_t *) pArgs);
760 
761         case AM_HAL_MCUCTRL_CONTROL_EXTCLK32M_DISABLE:
762             return mcuctrl_ctrl_HFXTAL_disable((am_hal_mcuctrl_control_arg_t *) pArgs);
763 
764         default:
765             return AM_HAL_STATUS_INVALID_ARG;
766     }
767 
768     //
769     // Return success status.
770     //
771     return AM_HAL_STATUS_SUCCESS;
772 
773 } // am_hal_mcuctrl_control()
774 
775 // ****************************************************************************
776 //
777 //  am_hal_mcuctrl_status_get()
778 // This function returns  current status of the MCUCTRL as obtained from
779 // various registers of the MCUCTRL block.
780 //
781 // ****************************************************************************
782 uint32_t
am_hal_mcuctrl_status_get(am_hal_mcuctrl_status_t * psStatus)783 am_hal_mcuctrl_status_get(am_hal_mcuctrl_status_t *psStatus)
784 {
785     uint32_t ui32Status;
786 
787     if ( psStatus == NULL )
788     {
789         return AM_HAL_STATUS_INVALID_ARG;
790     }
791 
792     psStatus->bDebuggerLockout =
793         _FLD2VAL(MCUCTRL_DEBUGGER_LOCKOUT, MCUCTRL->DEBUGGER);
794 
795     psStatus->bADCcalibrated =
796         _FLD2VAL(MCUCTRL_ADCCAL_ADCCALIBRATED, MCUCTRL->ADCCAL);
797 
798     psStatus->bBattLoadEnabled =
799         _FLD2VAL(MCUCTRL_ADCBATTLOAD_BATTLOAD, MCUCTRL->ADCBATTLOAD);
800 
801     ui32Status = MCUCTRL->BOOTLOADER;
802 
803     psStatus->bSecBootOnColdRst =
804         (_FLD2VAL(MCUCTRL_BOOTLOADER_SECBOOT, ui32Status) != MCUCTRL_BOOTLOADER_SECBOOT_ERROR);
805     psStatus->bSecBootOnWarmRst =
806         (_FLD2VAL(MCUCTRL_BOOTLOADER_SECBOOTONRST, ui32Status) != MCUCTRL_BOOTLOADER_SECBOOTONRST_ERROR);
807 
808     return AM_HAL_STATUS_SUCCESS;
809 
810 } // am_hal_mcuctrl_status_get()
811 
812 // ****************************************************************************
813 //
814 //  am_hal_mcuctrl_info_get()
815 //  Get information of the given MCUCTRL item.
816 //
817 // ****************************************************************************
818 uint32_t
am_hal_mcuctrl_info_get(am_hal_mcuctrl_infoget_e eInfoGet,void * pInfo)819 am_hal_mcuctrl_info_get(am_hal_mcuctrl_infoget_e eInfoGet, void *pInfo)
820 {
821     am_hal_mcuctrl_feature_t *psFeature;
822 
823     if ( pInfo == NULL )
824     {
825         return AM_HAL_STATUS_INVALID_ARG;
826     }
827 
828     switch ( eInfoGet )
829     {
830         case AM_HAL_MCUCTRL_INFO_FEATURES_AVAIL:
831             psFeature = (am_hal_mcuctrl_feature_t*)pInfo;
832             psFeature->eDTCMSize = AM_HAL_MCUCTRL_DTCM_384K;
833             psFeature->eSharedSRAMSize = (am_hal_mcuctrl_ssram_e)MCUCTRL->SKU_b.SKUSRAMSIZE;
834             psFeature->eMRAMSize = (am_hal_mcuctrl_mram_e)MCUCTRL->SKU_b.SKUMRAMSIZE;
835             psFeature->bTurboSpot = (MCUCTRL->SKU_b.SKUTURBOSPOT > 0);
836             psFeature->bDisplayCtrl = (MCUCTRL->SKU_b.SKUMIPIDSI > 0);
837             psFeature->bGPU = (MCUCTRL->SKU_b.SKUGFX > 0);
838             psFeature->bUSB = (MCUCTRL->SKU_b.SKUUSB > 0);
839             psFeature->bSecBootFeature = (MCUCTRL->SKU_b.SKUSECURESPOT > 0);
840             break;
841 
842         case AM_HAL_MCUCTRL_INFO_DEVICEID:
843             device_info_get((am_hal_mcuctrl_device_t *)pInfo);
844             break;
845 
846         default:
847             return AM_HAL_STATUS_INVALID_ARG;
848     }
849 
850     //
851     // Return success status.
852     //
853     return AM_HAL_STATUS_SUCCESS;
854 
855 } // am_hal_mcuctrl_info_get()
856 
857 //*****************************************************************************
858 //
859 // End Doxygen group.
860 //! @}
861 //
862 //*****************************************************************************
863