1 /***************************************************************************//**
2  * @file
3  * @brief Reset Management Unit (RMU) peripheral module 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_rmu.h"
32 #if (defined(RMU_COUNT) && (RMU_COUNT > 0)) || (_EMU_RSTCTRL_MASK)
33 
34 #include "sl_common.h"
35 #include "em_emu.h"
36 #include "em_bus.h"
37 
38 /***************************************************************************//**
39  * @addtogroup rmu RMU - Reset Management Unit
40  * @brief Reset Management Unit (RMU) Peripheral API
41  * @details
42  *  This module contains functions to control the RMU peripheral of Silicon
43  *  Labs 32-bit MCUs and SoCs. RMU ensures correct reset operation and is
44  *  responsible for connecting the different reset sources to the reset lines of
45  *  the MCU or SoC.
46  * @{
47  ******************************************************************************/
48 
49 /*******************************************************************************
50  *****************************     DEFINES     *********************************
51  ******************************************************************************/
52 
53 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
54 
55 #if defined(_RMU_RSTCAUSE_MASK)
56 
57 /** Reset cause XMASKS for series-0 and series-1 devices.
58     Reset cause zero and "don't care" bit definitions (XMASKs).
59     An XMASK 1 bit marks a bit that must be zero in RMU_RSTCAUSE. A 0 in XMASK
60     is a "don't care" bit in RMU_RSTCAUSE if also 0 in resetCauseMask
61     in @ref RMU_ResetCauseMasks_Typedef. */
62 
63 /* EFM32G */
64 #if (_RMU_RSTCAUSE_MASK == 0x0000007FUL)
65 #define RMU_RSTCAUSE_PORST_XMASK         0x00000000UL /** 0000000000000000  < Power On Reset */
66 #define RMU_RSTCAUSE_BODUNREGRST_XMASK   0x00000001UL /** 0000000000000001  < Brown Out Detector Unregulated Domain Reset */
67 #define RMU_RSTCAUSE_BODREGRST_XMASK     0x0000001BUL /** 0000000000011011  < Brown Out Detector Regulated Domain Reset */
68 #define RMU_RSTCAUSE_EXTRST_XMASK        0x00000003UL /** 0000000000000011  < External Pin Reset */
69 #define RMU_RSTCAUSE_WDOGRST_XMASK       0x00000003UL /** 0000000000000011  < Watchdog Reset */
70 #define RMU_RSTCAUSE_LOCKUPRST_XMASK     0x0000001FUL /** 0000000000011111  < LOCKUP Reset */
71 #define RMU_RSTCAUSE_SYSREQRST_XMASK     0x0000001FUL /** 0000000000011111  < System Request Reset */
72 #define NUM_RSTCAUSES                               7
73 
74 /* EFM32TG, EFM32HG, EZR32HG, EFM32ZG */
75 #elif (_RMU_RSTCAUSE_MASK == 0x000007FFUL)
76 #define RMU_RSTCAUSE_PORST_XMASK         0x00000000UL /** 0000000000000000  < Power On Reset */
77 #define RMU_RSTCAUSE_BODUNREGRST_XMASK   0x00000081UL /** 0000000010000001  < Brown Out Detector Unregulated Domain Reset */
78 #define RMU_RSTCAUSE_BODREGRST_XMASK     0x00000091UL /** 0000000010010001  < Brown Out Detector Regulated Domain Reset */
79 #define RMU_RSTCAUSE_EXTRST_XMASK        0x00000001UL /** 0000000000000001  < External Pin Reset */
80 #define RMU_RSTCAUSE_WDOGRST_XMASK       0x00000003UL /** 0000000000000011  < Watchdog Reset */
81 #define RMU_RSTCAUSE_LOCKUPRST_XMASK     0x0000EFDFUL /** 1110111111011111  < LOCKUP Reset */
82 #define RMU_RSTCAUSE_SYSREQRST_XMASK     0x0000EF9FUL /** 1110111110011111  < System Request Reset */
83 #define RMU_RSTCAUSE_EM4RST_XMASK        0x00000719UL /** 0000011100011001  < EM4 Reset */
84 #define RMU_RSTCAUSE_EM4WURST_XMASK      0x00000619UL /** 0000011000011001  < EM4 Wake-up Reset */
85 #define RMU_RSTCAUSE_BODAVDD0_XMASK      0x0000041FUL /** 0000010000011111  < AVDD0 Bod Reset. */
86 #define RMU_RSTCAUSE_BODAVDD1_XMASK      0x0000021FUL /** 0000001000011111  < AVDD1 Bod Reset. */
87 #define NUM_RSTCAUSES                              11
88 
89 /* EFM32GG, EFM32LG, EZR32LG, EFM32WG, EZR32WG */
90 #elif (_RMU_RSTCAUSE_MASK == 0x0000FFFFUL)
91 #define RMU_RSTCAUSE_PORST_XMASK         0x00000000UL /** 0000000000000000  < Power On Reset */
92 #define RMU_RSTCAUSE_BODUNREGRST_XMASK   0x00000081UL /** 0000000010000001  < Brown Out Detector Unregulated Domain Reset */
93 #define RMU_RSTCAUSE_BODREGRST_XMASK     0x00000091UL /** 0000000010010001  < Brown Out Detector Regulated Domain Reset */
94 #define RMU_RSTCAUSE_EXTRST_XMASK        0x00000001UL /** 0000000000000001  < External Pin Reset */
95 #define RMU_RSTCAUSE_WDOGRST_XMASK       0x00000003UL /** 0000000000000011  < Watchdog Reset */
96 #define RMU_RSTCAUSE_LOCKUPRST_XMASK     0x0000EFDFUL /** 1110111111011111  < LOCKUP Reset */
97 #define RMU_RSTCAUSE_SYSREQRST_XMASK     0x0000EF9FUL /** 1110111110011111  < System Request Reset */
98 #define RMU_RSTCAUSE_EM4RST_XMASK        0x00000719UL /** 0000011100011001  < EM4 Reset */
99 #define RMU_RSTCAUSE_EM4WURST_XMASK      0x00000619UL /** 0000011000011001  < EM4 Wake-up Reset */
100 #define RMU_RSTCAUSE_BODAVDD0_XMASK      0x0000041FUL /** 0000010000011111  < AVDD0 Bod Reset */
101 #define RMU_RSTCAUSE_BODAVDD1_XMASK      0x0000021FUL /** 0000001000011111  < AVDD1 Bod Reset */
102 #define RMU_RSTCAUSE_BUBODVDDDREG_XMASK  0x00000001UL /** 0000000000000001  < Backup Brown Out Detector, VDD_DREG */
103 #define RMU_RSTCAUSE_BUBODBUVIN_XMASK    0x00000001UL /** 0000000000000001  < Backup Brown Out Detector, BU_VIN */
104 #define RMU_RSTCAUSE_BUBODUNREG_XMASK    0x00000001UL /** 0000000000000001  < Backup Brown Out Detector Unregulated Domain */
105 #define RMU_RSTCAUSE_BUBODREG_XMASK      0x00000001UL /** 0000000000000001  < Backup Brown Out Detector Regulated Domain */
106 #define RMU_RSTCAUSE_BUMODERST_XMASK     0x00000001UL /** 0000000000000001  < Backup mode reset */
107 #define NUM_RSTCAUSES                              16
108 
109 /* EFM32xG1, EFM32xG12, EFM32xG13 */
110 #elif ((_RMU_RSTCAUSE_MASK & 0x0FFFFFFF) == 0x00010F1DUL)
111 #define RMU_RSTCAUSE_PORST_XMASK         0x00000000UL /** 0000000000000000  < Power On Reset */
112 #define RMU_RSTCAUSE_BODAVDD_XMASK       0x00000001UL /** 0000000000000001  < AVDD BOD Reset */
113 #define RMU_RSTCAUSE_BODDVDD_XMASK       0x00000001UL /** 0000000000000001  < DVDD BOD Reset */
114 #define RMU_RSTCAUSE_BODREGRST_XMASK     0x00000001UL /** 0000000000000001  < Regulated Domain (DEC) BOD Reset */
115 #define RMU_RSTCAUSE_EXTRST_XMASK        0x00000001UL /** 0000000000000001  < External Pin Reset */
116 #define RMU_RSTCAUSE_LOCKUPRST_XMASK     0x0000001DUL /** 0000000000011101  < LOCKUP Reset */
117 #define RMU_RSTCAUSE_SYSREQRST_XMASK     0x0000001DUL /** 0000000000011101  < System Request Reset */
118 #define RMU_RSTCAUSE_WDOGRST_XMASK       0x0000001DUL /** 0000000000011101  < Watchdog Reset */
119 #define RMU_RSTCAUSE_EM4RST_XMASK        0x0000001DUL /** 0000000000011101  < EM4H/S Reset */
120 #define NUM_RSTCAUSES                               9
121 
122 /* EFM32GG11 */
123 #elif ((_RMU_RSTCAUSE_MASK & 0x0FFFFFFF) == 0x00011F1DUL)
124 #define RMU_RSTCAUSE_PORST_XMASK         0x00000000UL /** 0000000000000000  < Power On Reset */
125 #define RMU_RSTCAUSE_BODAVDD_XMASK       0x00000001UL /** 0000000000000001  < AVDD BOD Reset */
126 #define RMU_RSTCAUSE_BODDVDD_XMASK       0x00000001UL /** 0000000000000001  < DVDD BOD Reset */
127 #define RMU_RSTCAUSE_BODREGRST_XMASK     0x00000001UL /** 0000000000000001  < Regulated Domain (DEC) BOD Reset */
128 #define RMU_RSTCAUSE_EXTRST_XMASK        0x00000001UL /** 0000000000000001  < External Pin Reset */
129 #define RMU_RSTCAUSE_LOCKUPRST_XMASK     0x0000001DUL /** 0000000000011101  < LOCKUP Reset */
130 #define RMU_RSTCAUSE_SYSREQRST_XMASK     0x0000001DUL /** 0000000000011101  < System Request Reset */
131 #define RMU_RSTCAUSE_WDOGRST_XMASK       0x0000001DUL /** 0000000000011101  < Watchdog Reset */
132 #define RMU_RSTCAUSE_BUMODERST_XMASK     0x0000001DUL /** 0000000000011101  < Backup mode reset */
133 #define RMU_RSTCAUSE_EM4RST_XMASK        0x0000001DUL /** 0000000000011101  < EM4H/S Reset */
134 #define NUM_RSTCAUSES                              10
135 
136 #else
137 #error "RMU_RSTCAUSE XMASKs are not defined for this family."
138 #endif
139 
140 /* Pin reset definitions. */
141 #define LB_CLW0           (*((volatile uint32_t *)(LOCKBITS_BASE) +122))
142 #define LB_CLW0_PINRESETSOFT    (1 << 2)
143 
144 #if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_80)
145 /* Fix for errata EMU_E208 - Occasional Full Reset After Exiting EM4H. */
146 #define ERRATA_FIX_EMU_E208_EN
147 #endif
148 
149 #endif /* #if defined(_RMU_RSTCAUSE_MASK) */
150 
151 /*******************************************************************************
152  *******************************   STRUCTS   ***********************************
153  ******************************************************************************/
154 
155 #if defined(_RMU_RSTCAUSE_MASK)
156 /** Reset cause mask type for series-0 and series-1 devices. */
157 typedef struct {
158   /** Reset cause 1 bits. */
159   uint32_t resetCauseMask;
160   /** Reset cause 0 and "don't care" bits. */
161   uint32_t resetCauseZeroXMask;
162 } RMU_ResetCauseMasks_Typedef;
163 #endif
164 
165 /*******************************************************************************
166  *******************************   TYPEDEFS   **********************************
167  ******************************************************************************/
168 
169 #if defined(_RMU_RSTCAUSE_MASK)
170 /** Reset cause mask table. */
171 static const RMU_ResetCauseMasks_Typedef  resetCauseMasks[NUM_RSTCAUSES] =
172 {
173   { RMU_RSTCAUSE_PORST, RMU_RSTCAUSE_PORST_XMASK },
174 #if defined(RMU_RSTCAUSE_BODUNREGRST)
175   { RMU_RSTCAUSE_BODUNREGRST, RMU_RSTCAUSE_BODUNREGRST_XMASK },
176 #endif
177 #if defined(RMU_RSTCAUSE_BODREGRST)
178   { RMU_RSTCAUSE_BODREGRST, RMU_RSTCAUSE_BODREGRST_XMASK },
179 #endif
180 #if defined(RMU_RSTCAUSE_AVDDBOD)
181   { RMU_RSTCAUSE_AVDDBOD, RMU_RSTCAUSE_BODAVDD_XMASK },
182 #endif
183 #if defined(RMU_RSTCAUSE_DVDDBOD)
184   { RMU_RSTCAUSE_DVDDBOD, RMU_RSTCAUSE_BODDVDD_XMASK },
185 #endif
186 #if defined(RMU_RSTCAUSE_DECBOD)
187   { RMU_RSTCAUSE_DECBOD, RMU_RSTCAUSE_BODREGRST_XMASK },
188 #endif
189   { RMU_RSTCAUSE_EXTRST, RMU_RSTCAUSE_EXTRST_XMASK },
190   { RMU_RSTCAUSE_WDOGRST, RMU_RSTCAUSE_WDOGRST_XMASK },
191   { RMU_RSTCAUSE_LOCKUPRST, RMU_RSTCAUSE_LOCKUPRST_XMASK },
192   { RMU_RSTCAUSE_SYSREQRST, RMU_RSTCAUSE_SYSREQRST_XMASK },
193 #if defined(RMU_RSTCAUSE_EM4RST)
194   { RMU_RSTCAUSE_EM4RST, RMU_RSTCAUSE_EM4RST_XMASK },
195 #endif
196 #if defined(RMU_RSTCAUSE_EM4WURST)
197   { RMU_RSTCAUSE_EM4WURST, RMU_RSTCAUSE_EM4WURST_XMASK },
198 #endif
199 #if defined(RMU_RSTCAUSE_BODAVDD0)
200   { RMU_RSTCAUSE_BODAVDD0, RMU_RSTCAUSE_BODAVDD0_XMASK },
201 #endif
202 #if defined(RMU_RSTCAUSE_BODAVDD1)
203   { RMU_RSTCAUSE_BODAVDD1, RMU_RSTCAUSE_BODAVDD1_XMASK },
204 #endif
205 #if defined(BU_PRESENT) && defined(_SILICON_LABS_32B_SERIES_0)
206   { RMU_RSTCAUSE_BUBODVDDDREG, RMU_RSTCAUSE_BUBODVDDDREG_XMASK },
207   { RMU_RSTCAUSE_BUBODBUVIN, RMU_RSTCAUSE_BUBODBUVIN_XMASK },
208   { RMU_RSTCAUSE_BUBODUNREG, RMU_RSTCAUSE_BUBODUNREG_XMASK },
209   { RMU_RSTCAUSE_BUBODREG, RMU_RSTCAUSE_BUBODREG_XMASK },
210   { RMU_RSTCAUSE_BUMODERST, RMU_RSTCAUSE_BUMODERST_XMASK },
211 #elif defined(RMU_RSTCAUSE_BUMODERST)
212   { RMU_RSTCAUSE_BUMODERST, RMU_RSTCAUSE_BUMODERST_XMASK },
213 #endif
214 };
215 #endif /* #if defined(_RMU_RSTCAUSE_MASK) */
216 
217 /*******************************************************************************
218  ********************************     TEST     ********************************
219  ******************************************************************************/
220 #if defined(EMLIB_REGRESSION_TEST)
221 /* A test variable that replaces the RSTCAUSE cause register when testing
222    the RMU_ResetCauseGet function. */
223 extern uint32_t rstCause;
224 #endif
225 
226 /** @endcond */
227 
228 /*******************************************************************************
229  **************************   GLOBAL FUNCTIONS   *******************************
230  ******************************************************************************/
231 
232 /***************************************************************************//**
233  * @brief
234  *   Disable/enable reset for various peripherals and signal sources.
235  *
236  * @param[in] reset Reset types to enable/disable.s
237  *
238  * @param[in] mode  Reset mode.
239  ******************************************************************************/
RMU_ResetControl(RMU_Reset_TypeDef reset,RMU_ResetMode_TypeDef mode)240 void RMU_ResetControl(RMU_Reset_TypeDef reset, RMU_ResetMode_TypeDef mode)
241 {
242   /* Note that the RMU supports bit-band access, but not peripheral bit-field set/clear. */
243 #if defined(_RMU_CTRL_PINRMODE_MASK)
244   uint32_t val;
245 #endif
246   uint32_t shift;
247 
248   shift = SL_CTZ((uint32_t)reset);
249 #if defined(_EMU_RSTCTRL_MASK)
250   BUS_RegBitWrite(&EMU->RSTCTRL, (uint32_t)shift, mode ? 1 : 0);
251 #elif defined(_RMU_CTRL_PINRMODE_MASK)
252   val = (uint32_t)mode << shift;
253   RMU->CTRL = (RMU->CTRL & ~reset) | val;
254 #else
255   BUS_RegBitWrite(&RMU->CTRL, (uint32_t)shift, mode ? 1 : 0);
256 #endif
257 }
258 
259 /***************************************************************************//**
260  * @brief
261  *   Clear the reset cause register.
262  *
263  * @details
264  *   This function clears all the reset cause bits of the RSTCAUSE register.
265  *   The reset cause bits must be cleared by software before a new reset occurs.
266  *   Otherwise, reset causes may accumulate. See @ref RMU_ResetCauseGet().
267  ******************************************************************************/
RMU_ResetCauseClear(void)268 void RMU_ResetCauseClear(void)
269 {
270 #if defined(_EMU_RSTCTRL_MASK)
271   EMU->CMD_SET = EMU_CMD_RSTCAUSECLR;
272 #else
273   RMU->CMD = RMU_CMD_RCCLR;
274 #endif
275 
276 #if defined(EMU_AUXCTRL_HRCCLR)
277   {
278     uint32_t locked;
279 
280     /* Clear reset causes not cleared with the RMU CMD register. */
281     /* (If EMU registers are locked, they must be unlocked first) */
282     locked = EMU->LOCK & EMU_LOCK_LOCKKEY_LOCKED;
283     if (locked) {
284       EMU_Unlock();
285     }
286 
287     BUS_RegBitWrite(&(EMU->AUXCTRL), _EMU_AUXCTRL_HRCCLR_SHIFT, 1);
288     BUS_RegBitWrite(&(EMU->AUXCTRL), _EMU_AUXCTRL_HRCCLR_SHIFT, 0);
289 
290     if (locked) {
291       EMU_Lock();
292     }
293   }
294 #endif
295 }
296 
297 /***************************************************************************//**
298  * @brief
299  *   Get the cause of the last reset.
300  *
301  * @details
302  *   To be useful, the reset cause must be cleared by software before a new
303  *   reset occurs. Otherwise, reset causes may accumulate. See @ref
304  *   RMU_ResetCauseClear(). This function call will return the main cause for
305  *   reset, which can be a bit mask (several causes) and clear away "noise".
306  *
307  * @return
308  *   A reset cause mask. See the reference manual for a description
309  *   of the reset cause mask.
310  ******************************************************************************/
RMU_ResetCauseGet(void)311 uint32_t RMU_ResetCauseGet(void)
312 {
313 #if defined(_EMU_RSTCAUSE_MASK)
314 #if defined(EMLIB_REGRESSION_TEST)
315   return rstCause;
316 #else
317   return EMU->RSTCAUSE;
318 #endif
319 #endif
320 
321 #if defined(_RMU_RSTCAUSE_MASK)
322 #if !defined(EMLIB_REGRESSION_TEST)
323   uint32_t rstCause = RMU->RSTCAUSE;
324 #endif
325   uint32_t validRstCause = 0;
326   uint32_t zeroXMask;
327   uint32_t i;
328 
329   for (i = 0; i < NUM_RSTCAUSES; i++) {
330     zeroXMask = resetCauseMasks[i].resetCauseZeroXMask;
331 #if defined(_SILICON_LABS_32B_SERIES_1)
332     /* Handle soft/hard pin reset. */
333     if (!(LB_CLW0 & LB_CLW0_PINRESETSOFT)) {
334       /* RSTCAUSE_EXTRST must be 0 if pin reset is configured as hard reset. */
335       switch (resetCauseMasks[i].resetCauseMask) {
336         case RMU_RSTCAUSE_LOCKUPRST:
337         /* Fallthrough */
338         case RMU_RSTCAUSE_SYSREQRST:
339         /* Fallthrough */
340         case RMU_RSTCAUSE_WDOGRST:
341         /* Fallthrough */
342         case RMU_RSTCAUSE_EM4RST:
343           zeroXMask |= RMU_RSTCAUSE_EXTRST;
344           break;
345         default:
346           /* MISRA requires a default case. */
347           break;
348       }
349     }
350 #endif
351 
352 #if defined(_EMU_EM4CTRL_MASK) && defined(ERRATA_FIX_EMU_E208_EN)
353     /* Ignore BOD flags impacted by EMU_E208. */
354     if (*(volatile uint32_t *)(EMU_BASE + 0x88) & (0x1 << 8)) {
355       zeroXMask &= ~(RMU_RSTCAUSE_DECBOD
356                      | RMU_RSTCAUSE_DVDDBOD
357                      | RMU_RSTCAUSE_AVDDBOD);
358     }
359 #endif
360 
361     /* Check reset cause requirements. Note that a bit is "don't care" if 0 in
362        both resetCauseMask and resetCauseZeroXMask. */
363     if ((rstCause & resetCauseMasks[i].resetCauseMask)
364         && !(rstCause & zeroXMask)) {
365       /* Add this reset-cause to the mask of qualified reset-causes. */
366       validRstCause |= resetCauseMasks[i].resetCauseMask;
367     }
368   }
369 #if defined(_EMU_EM4CTRL_MASK) && defined(ERRATA_FIX_EMU_E208_EN)
370   /* Clear BOD flags impacted by EMU_E208. */
371   if (validRstCause & RMU_RSTCAUSE_EM4RST) {
372     validRstCause &= ~(RMU_RSTCAUSE_DECBOD
373                        | RMU_RSTCAUSE_DVDDBOD
374                        | RMU_RSTCAUSE_AVDDBOD);
375   }
376 #endif
377   return validRstCause;
378 #endif
379 }
380 
381 /** @} (end addtogroup rmu) */
382 #endif /* defined(RMU_COUNT) && (RMU_COUNT > 0) */
383