1 /***************************************************************************//**
2  * @file
3  * @brief Device initialization for HFXO.
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
7  *******************************************************************************
8  *
9  * SPDX-License-Identifier: Zlib
10  *
11  * The licensor of this software is Silicon Laboratories Inc.
12  *
13  * This software is provided 'as-is', without any express or implied
14  * warranty. In no event will the authors be held liable for any damages
15  * arising from the use of this software.
16  *
17  * Permission is granted to anyone to use this software for any purpose,
18  * including commercial applications, and to alter it and redistribute it
19  * freely, subject to the following restrictions:
20  *
21  * 1. The origin of this software must not be misrepresented; you must not
22  *    claim that you wrote the original software. If you use this software
23  *    in a product, an acknowledgment in the product documentation would be
24  *    appreciated but is not required.
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  * 3. This notice may not be removed or altered from any source distribution.
28  *
29  ******************************************************************************/
30 #include "sl_device_init_hfxo.h"
31 #include "sl_device_init_hfxo_config.h"
32 
33 #include "em_cmu.h"
34 
35 // Fetch CTUNE value from USERDATA page as a manufacturing token
36 #define MFG_CTUNE_ADDR 0x0FE00100UL
37 #define MFG_CTUNE_VAL  (*((uint16_t *) (MFG_CTUNE_ADDR)))
38 
sl_device_init_hfxo(void)39 sl_status_t sl_device_init_hfxo(void)
40 {
41   CMU_HFXOInit_TypeDef hfxoInit = CMU_HFXOINIT_DEFAULT;
42   hfxoInit.mode = SL_DEVICE_INIT_HFXO_MODE;
43 
44   int ctune = -1;
45 
46 #if defined(_DEVINFO_MODXOCAL_HFXOCTUNEXIANA_MASK)
47   // Use HFXO tuning value from DEVINFO if available (PCB modules)
48   if ((DEVINFO->MODULEINFO & _DEVINFO_MODULEINFO_HFXOCALVAL_MASK) == 0) {
49     ctune = DEVINFO->MODXOCAL & _DEVINFO_MODXOCAL_HFXOCTUNEXIANA_MASK;
50   }
51 #endif
52 
53   // Use HFXO tuning value from MFG token in UD page if not already set
54   if ((ctune == -1) && (MFG_CTUNE_VAL != 0xFFFF)) {
55     ctune = MFG_CTUNE_VAL;
56   }
57 
58   // Use HFXO tuning value from configuration header as fallback
59   if (ctune == -1) {
60     ctune = SL_DEVICE_INIT_HFXO_CTUNE;
61   }
62 
63   // Configure CTUNE XI and XO.
64   if (ctune != -1) {
65     hfxoInit.ctuneXiAna = (uint8_t)ctune;
66 
67     // Ensure CTUNE XO plus a delta is within the correct range. The delta accounts for internal chip
68     // load imbalance on some series 2 chips.
69     ctune += CMU_HFXOCTuneDeltaGet();
70     if (ctune < 0) {
71       ctune = 0;
72     } else if (ctune > ((int)(_HFXO_XTALCTRL_CTUNEXOANA_MASK >> _HFXO_XTALCTRL_CTUNEXOANA_SHIFT))) {
73       ctune = (int)(_HFXO_XTALCTRL_CTUNEXOANA_MASK >> _HFXO_XTALCTRL_CTUNEXOANA_SHIFT);
74     }
75     hfxoInit.ctuneXoAna = ctune;
76   }
77 
78   SystemHFXOClockSet(SL_DEVICE_INIT_HFXO_FREQ);
79   CMU_HFXOInit(&hfxoInit);
80 
81   return SL_STATUS_OK;
82 }
83