1 /***************************************************************************//**
2  * @file
3  * @brief System Peripheral API
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2018 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 
31 #include "em_system.h"
32 #include "sl_assert.h"
33 #include <stddef.h>
34 #if defined(SYSCFG_PRESENT)
35 #include "em_syscfg.h"
36 #endif
37 /***************************************************************************//**
38  * @addtogroup system
39  * @{
40  ******************************************************************************/
41 
42 /*******************************************************************************
43  *********************************   DEFINES   *********************************
44  ******************************************************************************/
45 
46 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
47 
48 /* Bit mask used to extract the part number value without the new naming
49  * bitfield. */
50 #define SYSCFG_CHIPREV_PARTNUMBER1  0xFE0
51 #define SYSCFG_CHIPREV_PARTNUMBER0  0xF
52 
53 /* Bit mask to convert NON-SECURE to SECURE */
54 #define CONVERT_NS_TO_S (~(1 << 28U))
55 
56 /** @endcond */
57 
58 /*******************************************************************************
59  **************************   GLOBAL FUNCTIONS   *******************************
60  ******************************************************************************/
61 
62 /***************************************************************************//**
63  * @brief
64  *   Get a chip major/minor revision.
65  *
66  * @param[out] rev
67  *   A location to place the chip revision information.
68  ******************************************************************************/
SYSTEM_ChipRevisionGet(SYSTEM_ChipRevision_TypeDef * rev)69 void SYSTEM_ChipRevisionGet(SYSTEM_ChipRevision_TypeDef *rev)
70 {
71 #if defined(_SYSCFG_CHIPREV_FAMILY_MASK) || defined(_SYSCFG_CHIPREV_PARTNUMBER_MASK)
72   /* On series-2 (and higher) the revision info is in the SYSCFG->CHIPREV register. */
73 #if defined(CMU_CLKEN0_SYSCFG)
74   CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
75 #endif
76   uint32_t chiprev = SYSCFG_readChipRev();
77 #if defined(_SYSCFG_CHIPREV_PARTNUMBER_MASK)
78   rev->partNumber = ((chiprev & SYSCFG_CHIPREV_PARTNUMBER1) >> 5) | (chiprev & SYSCFG_CHIPREV_PARTNUMBER0);
79 #else
80   rev->family = (chiprev & _SYSCFG_CHIPREV_FAMILY_MASK) >> _SYSCFG_CHIPREV_FAMILY_SHIFT;
81 #endif
82   rev->major  = (chiprev & _SYSCFG_CHIPREV_MAJOR_MASK)  >> _SYSCFG_CHIPREV_MAJOR_SHIFT;
83   rev->minor  = (chiprev & _SYSCFG_CHIPREV_MINOR_MASK)  >> _SYSCFG_CHIPREV_MINOR_SHIFT;
84 #else
85   uint8_t tmp;
86 
87   EFM_ASSERT(rev);
88 
89   /* CHIP FAMILY bit [5:2] */
90   tmp  = (uint8_t)(((ROMTABLE->PID1 & _ROMTABLE_PID1_FAMILYMSB_MASK)
91                     >> _ROMTABLE_PID1_FAMILYMSB_SHIFT) << 2);
92   /* CHIP FAMILY bit [1:0] */
93   tmp |=  (uint8_t)((ROMTABLE->PID0 & _ROMTABLE_PID0_FAMILYLSB_MASK)
94                     >> _ROMTABLE_PID0_FAMILYLSB_SHIFT);
95   rev->family = tmp;
96 
97   /* CHIP MAJOR bit [3:0] */
98   rev->major = (uint8_t)((ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK)
99                          >> _ROMTABLE_PID0_REVMAJOR_SHIFT);
100 
101   /* CHIP MINOR bit [7:4] */
102   tmp  = (uint8_t)(((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK)
103                     >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4);
104   /* CHIP MINOR bit [3:0] */
105   tmp |= (uint8_t)((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK)
106                    >> _ROMTABLE_PID3_REVMINORLSB_SHIFT);
107   rev->minor = tmp;
108 #endif
109 }
110 
111 /***************************************************************************//**
112  * @brief
113  *    Get a factory calibration value for a given peripheral register.
114  *
115  * @param[in] regAddress
116  *    The peripheral calibration register address to get a calibration value for. If
117  *    the calibration value is found, this register is updated with the
118  *    calibration value.
119  *
120  * @return
121  *    True if a calibration value exists, false otherwise.
122  ******************************************************************************/
SYSTEM_GetCalibrationValue(volatile uint32_t * regAddress)123 bool SYSTEM_GetCalibrationValue(volatile uint32_t *regAddress)
124 {
125   SYSTEM_CalAddrVal_TypeDef * p, * end;
126 
127   uint32_t s_regAddress = (uint32_t)regAddress;
128   s_regAddress = s_regAddress & CONVERT_NS_TO_S;
129 
130 #if defined(MSC_FLASH_CHIPCONFIG_MEM_BASE)
131   p   = (SYSTEM_CalAddrVal_TypeDef *)MSC_FLASH_CHIPCONFIG_MEM_BASE;
132   end = (SYSTEM_CalAddrVal_TypeDef *)MSC_FLASH_CHIPCONFIG_MEM_END;
133 #else
134   p   = (SYSTEM_CalAddrVal_TypeDef *)(DEVINFO_BASE & 0xFFFFF000U);
135   end = (SYSTEM_CalAddrVal_TypeDef *)DEVINFO_BASE;
136 #endif
137 
138   for (; p < end; p++) {
139     if (p->address == 0) {
140       /* p->address == 0 marks the end of the table */
141       return false;
142     }
143     if (p->address == s_regAddress) {
144       *regAddress = p->calValue;
145       return true;
146     }
147   }
148   /* Nothing found for regAddress. */
149   return false;
150 }
151 
152 /***************************************************************************//**
153  * @brief
154  *   Get family security capability.
155  *
156  * @note
157  *   This function retrieves the family security capability based on the
158  *   device number. The device number is one letter and 3 digits:
159  *   DEVICENUMBER = (alpha-'A')*1000 + numeric. i.e. 0d = "A000"; 1123d = "B123".
160  *   The security capabilities are represented by ::SYSTEM_SecurityCapability_TypeDef.
161  *
162  * @return
163  *   Security capability of MCU.
164  ******************************************************************************/
SYSTEM_GetSecurityCapability(void)165 SYSTEM_SecurityCapability_TypeDef SYSTEM_GetSecurityCapability(void)
166 {
167   SYSTEM_SecurityCapability_TypeDef sc;
168 
169 #if (_SILICON_LABS_32B_SERIES == 0)
170   sc = securityCapabilityNA;
171 #elif (_SILICON_LABS_32B_SERIES == 1)
172   sc = securityCapabilityBasic;
173 #else
174   sc = securityCapabilityUnknown;
175 #endif
176 
177 #if (_SILICON_LABS_32B_SERIES == 2)
178   uint16_t mcuFeatureSetMajor;
179   uint16_t deviceNumber;
180   deviceNumber = SYSTEM_GetPartNumber();
181   mcuFeatureSetMajor = 'A' + (deviceNumber / 1000);
182 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2)
183   // override feature set since BRD4182A Rev A00 -> rev B02 are marked "A"
184   mcuFeatureSetMajor = 'C';
185 #endif
186 
187   switch (mcuFeatureSetMajor) {
188     case 'A':
189       sc = securityCapabilitySE;
190       break;
191 
192     case 'B':
193       sc = securityCapabilityVault;
194       break;
195 
196     case 'C':
197       sc = securityCapabilityRoT;
198       break;
199 
200     default:
201       sc = securityCapabilityUnknown;
202       break;
203   }
204 #endif
205 
206   return sc;
207 }
208 
209 /** @} (end addtogroup system) */
210