1 //*****************************************************************************
2 //
3 //! @file am_hal_dcu.c
4 //!
5 //! @brief Implementation for Debug Control Unit functionality
6 //!
7 //! @addtogroup dcu_4p DCU - Debug Control Unit
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 #include "am_mcu_apollo.h"
48
49 #define CRYPTO_CC_IS_IDLE() while (CRYPTO->HOSTCCISIDLE_b.HOSTCCISIDLE == 0)
50
51 // Raw offset for 3b value corresponding to DCU value 1
52 uint32_t gStartOff = 0; // DCU value 1 corresponds to b[2:0]
53 uint64_t gDcuMask = AM_HAL_DCURAW_MASK;
54 uint64_t gDcuEnable = AM_HAL_DCURAW_ENABLE;
55 uint64_t gDcuDisable = AM_HAL_DCURAW_DISABLE;
56 volatile uint32_t *gpDcuEnable = &CRYPTO->HOSTDCUEN2;
57 volatile uint32_t *gpDcuLock = &CRYPTO->HOSTDCULOCK2;
58
59 //*****************************************************************************
60 //
61 //! @brief Get the Current RAW DCU Mask
62 //
63 //*****************************************************************************
64 static uint64_t
get_raw_dcu_mask(uint32_t ui32DcuMask,uint8_t threeBitVal)65 get_raw_dcu_mask(uint32_t ui32DcuMask, uint8_t threeBitVal)
66 {
67 uint32_t i = AM_HAL_DCU_NUMDCU;
68 uint64_t ui64Mask = 0;
69 uint32_t offset = gStartOff;
70 ui32DcuMask >>= 1; // DCU value 0 is not defined
71 while ( --i )
72 {
73 if (ui32DcuMask & 0x1)
74 {
75 ui64Mask |= (uint64_t)threeBitVal << offset;
76 }
77 offset += 3;
78 ui32DcuMask >>= 1;
79 }
80 return ui64Mask;
81 }
82
83 //*****************************************************************************
84 //
85 //! @brief Get the Current DCU Mask
86 //
87 //*****************************************************************************
88 static uint32_t
get_ui32_dcu_mask(uint64_t ui64DcuMask,uint8_t threeBitVal)89 get_ui32_dcu_mask(uint64_t ui64DcuMask, uint8_t threeBitVal)
90 {
91 uint32_t i = AM_HAL_DCU_NUMDCU;
92 uint32_t ui32Mask = 0;
93 ui64DcuMask >>= gStartOff;
94 while ( --i )
95 {
96 if ((ui64DcuMask & AM_HAL_DCURAWVAL_MASK) == threeBitVal)
97 {
98 ui32Mask |= (1 << (AM_HAL_DCU_NUMDCU - i - 1));
99 }
100 ui64DcuMask >>= 3;
101 }
102 return ui32Mask;
103 }
104
105 //*****************************************************************************
106 //
107 //! @brief Copy words from Register to Register
108 //
109 //*****************************************************************************
110 static void
copy_words(uint32_t * pDst,uint32_t * pSrc,uint32_t numWords)111 copy_words(uint32_t *pDst, uint32_t *pSrc, uint32_t numWords)
112 {
113 while (numWords--)
114 {
115 AM_REGVAL((pDst + numWords)) = AM_REGVAL((pSrc + numWords));
116 }
117 }
118
119 //*****************************************************************************
120 //
121 //! @brief Read DCU Lock
122 //!
123 //! @param pui64Val - Pointer to double word for returned data
124 //!
125 //! This will retrieve the DCU Lock information
126 //!
127 //! @return Returns AM_HAL_STATUS_SUCCESS on success
128 //
129 //*****************************************************************************
130 static
am_hal_dcu_raw_lock_status_get(uint64_t * pui64Val)131 uint32_t am_hal_dcu_raw_lock_status_get(uint64_t *pui64Val)
132 {
133 copy_words((uint32_t *)pui64Val, (uint32_t *)gpDcuLock, sizeof(uint64_t) / 4);
134 return AM_HAL_STATUS_SUCCESS;
135 }
136
137 //*****************************************************************************
138 //
139 //! @brief Read DCU Lock
140 //!
141 //! @param pui32Val - Pointer to word for returned data (Qualified DCU Mask)
142 //!
143 //! This will retrieve the DCU Lock information
144 //!
145 //! @return Returns AM_HAL_STATUS_SUCCESS on success
146 //
147 //*****************************************************************************
am_hal_dcu_lock_status_get(uint32_t * pui32Val)148 uint32_t am_hal_dcu_lock_status_get(uint32_t *pui32Val)
149 {
150 uint64_t ui64Lock;
151 uint32_t ui32Status;
152 if ((PWRCTRL->DEVPWRSTATUS_b.PWRSTCRYPTO == 0) || (CRYPTO->HOSTCCISIDLE_b.HOSTCCISIDLE == 0))
153 {
154 // Crypto is not accessible
155 return AM_HAL_STATUS_INVALID_OPERATION;
156 }
157 ui32Status = am_hal_dcu_raw_lock_status_get(&ui64Lock);
158 *pui32Val = get_ui32_dcu_mask(ui64Lock, AM_HAL_DCURAWVAL_MASK);
159 return ui32Status;
160 }
161
162 //*****************************************************************************
163 //
164 //! @brief Write DCU Lock
165 //!
166 //! @param val - double word for lock values
167 //!
168 //! This will lock the DCU from further changes
169 //!
170 //! @return Returns AM_HAL_STATUS_SUCCESS on success
171 //
172 //*****************************************************************************
173 static
am_hal_dcu_raw_lock(uint64_t ui64Mask)174 uint32_t am_hal_dcu_raw_lock(uint64_t ui64Mask)
175 {
176 //
177 // copy_words((uint32_t *)gpDcuLock, (uint32_t *)&ui64Mask, sizeof(uint64_t) / 4);
178 //
179 // In order to avoid a GCC compiler warning, we'll explicitly handle the
180 // call to copy_words() by replacing it with a couple of direct writes.
181 // Note that the writes are done in the same reverse order as copy_words()
182 // would do it.
183 //
184 gpDcuLock[1] = (uint32_t)(ui64Mask >> 32);
185 gpDcuLock[0] = (uint32_t)(ui64Mask >> 0);
186 CRYPTO_CC_IS_IDLE();
187 return AM_HAL_STATUS_SUCCESS;
188 } // am_hal_dcu_raw_lock()
189
190 //*****************************************************************************
191 //
192 //! @brief Write DCU Lock (Qualified Values)
193 //!
194 //! @param ui32Mask - Mask for lock values
195 //!
196 //! This will lock the DCU from further changes
197 //!
198 //! @return Returns AM_HAL_STATUS_SUCCESS on success
199 //
200 //*****************************************************************************
am_hal_dcu_lock(uint32_t ui32Mask)201 uint32_t am_hal_dcu_lock(uint32_t ui32Mask)
202 {
203 uint64_t ui64Lock;
204 if ((PWRCTRL->DEVPWRSTATUS_b.PWRSTCRYPTO == 0) || (CRYPTO->HOSTCCISIDLE_b.HOSTCCISIDLE == 0))
205 {
206 // Crypto is not accessible
207 return AM_HAL_STATUS_INVALID_OPERATION;
208 }
209 ui64Lock = get_raw_dcu_mask(ui32Mask, AM_HAL_DCURAWVAL_MASK);
210 return am_hal_dcu_raw_lock(ui64Lock);
211 }
212
213 //*****************************************************************************
214 //
215 //! @brief Read DCU Enables
216 //!
217 //! @param pui64Val - Pointer to double word for returned data
218 //!
219 //! This will get the current DCU Enable settings
220 //!
221 //! @return Returns AM_HAL_STATUS_SUCCESS on success
222 //
223 //*****************************************************************************
224 static
am_hal_dcu_raw_get(uint64_t * pui64Val)225 uint32_t am_hal_dcu_raw_get(uint64_t *pui64Val)
226 {
227 copy_words((uint32_t *)pui64Val, (uint32_t *)gpDcuEnable, sizeof(uint64_t) / 4);
228 return AM_HAL_STATUS_SUCCESS;
229 }
230
231 //*****************************************************************************
232 //
233 //! @brief Read DCU Enables (Qualified Values)
234 //!
235 //! @param pui32Val - Pointer to Mask for returned data
236 //!
237 //! This will get the current DCU Enable settings
238 //!
239 //! @return Returns AM_HAL_STATUS_SUCCESS on success
240 //
241 //*****************************************************************************
am_hal_dcu_get(uint32_t * pui32Val)242 uint32_t am_hal_dcu_get(uint32_t *pui32Val)
243 {
244 uint64_t ui64Enable;
245 uint32_t ui32Status;
246 if ((PWRCTRL->DEVPWRSTATUS_b.PWRSTCRYPTO == 0) || (CRYPTO->HOSTCCISIDLE_b.HOSTCCISIDLE == 0))
247 {
248 // Crypto is not accessible
249 return AM_HAL_STATUS_INVALID_OPERATION;
250 }
251 ui32Status = am_hal_dcu_raw_get(&ui64Enable);
252 *pui32Val = get_ui32_dcu_mask(ui64Enable, AM_HAL_DCURAWVAL_ENABLE);
253 return ui32Status;
254 }
255
256 //*****************************************************************************
257 //
258 //! @brief Update DCU Enable
259 //!
260 //! @param ui64Mask - DCU controls to be modified
261 //! @param bEnable - Whether to enable or disable
262 //!
263 //! This will update the DCU Enable settings, if not locked
264 //!
265 //! @return Returns AM_HAL_STATUS_SUCCESS on success
266 //
267 //*****************************************************************************
268 static
am_hal_dcu_raw_update(bool bEnable,uint64_t ui64Mask)269 uint32_t am_hal_dcu_raw_update(bool bEnable, uint64_t ui64Mask)
270 {
271 uint64_t dcuVal;
272 uint64_t dcuLock;
273 copy_words((uint32_t *)&dcuLock, (uint32_t *)gpDcuLock, sizeof(uint64_t) / 4);
274 if (ui64Mask & dcuLock)
275 {
276 return AM_HAL_STATUS_INVALID_OPERATION;
277 }
278 copy_words((uint32_t *)&dcuVal, (uint32_t *)gpDcuEnable, sizeof(uint64_t) / 4);
279 if (bEnable)
280 {
281 dcuVal = (dcuVal & ~ui64Mask) | (gDcuEnable & ui64Mask);
282 }
283 else
284 {
285 dcuVal = (dcuVal & ~ui64Mask) | (gDcuDisable & ui64Mask);
286 }
287 copy_words((uint32_t *)gpDcuEnable, (uint32_t *)&dcuVal, sizeof(uint64_t) / 4);
288 CRYPTO_CC_IS_IDLE();
289 return AM_HAL_STATUS_SUCCESS;
290 }
291
292 //*****************************************************************************
293 //
294 // Update DCU Enable (Qualified Values)
295 //
296 // This will update the DCU Enable settings, if not locked
297 //
298 //*****************************************************************************
am_hal_dcu_update(bool bEnable,uint32_t ui32Mask)299 uint32_t am_hal_dcu_update(bool bEnable, uint32_t ui32Mask)
300 {
301 uint64_t ui64Mask;
302 if ((PWRCTRL->DEVPWRSTATUS_b.PWRSTCRYPTO == 0) || (CRYPTO->HOSTCCISIDLE_b.HOSTCCISIDLE == 0))
303 {
304 // Crypto is not accessible
305 return AM_HAL_STATUS_INVALID_OPERATION;
306 }
307 ui64Mask = get_raw_dcu_mask(ui32Mask, AM_HAL_DCURAWVAL_MASK);
308 return am_hal_dcu_raw_update(bEnable, ui64Mask);
309 }
310
311 //*****************************************************************************
312 //
313 // DCU Disable - Using MCUCTRL Override
314 //
315 // This will update the MCUCTRL DCU Disable Override settings
316 // This can only further lock things if the corresponding DCU Enable was open
317 //
318 //*****************************************************************************
am_hal_dcu_mcuctrl_override(uint32_t ui32Mask)319 uint32_t am_hal_dcu_mcuctrl_override(uint32_t ui32Mask)
320 {
321 MCUCTRL->DEBUGGER = ui32Mask;
322 return AM_HAL_STATUS_SUCCESS;
323 }
324
325
326 //*****************************************************************************
327 //
328 // End Doxygen group.
329 //! @}
330 //
331 //*****************************************************************************
332