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