1 //*****************************************************************************
2 //
3 //! @file am_hal_mram.c
4 //!
5 //! @brief BootROM Helper Function Table
6 //!
7 //! @addtogroup mram4_4p MRAM Functionality
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 <stdint.h>
49 #include <stdbool.h>
50 #include "am_mcu_apollo.h"
51 #include "am_hal_bootrom_helper.h"
52
53
54 #define HLPRFNC_MAXSRC_ADDR 0x101D7FFC // Maximum src size for Apollo4 Plus
55
56 //#define INFO_ACCESS_WA
57
58
59 #define MRAM_OVERRIDE()
60 #define MRAM_REVERT()
61 #define MRAM_RECOVER()
62
63
64 //*****************************************************************************
65 //
66 // This programs up to N words of the Main MRAM
67 //
68 //*****************************************************************************
69 int
am_hal_mram_main_words_program(uint32_t ui32ProgramKey,uint32_t * pui32Src,uint32_t * pui32Dst,uint32_t ui32NumWords)70 am_hal_mram_main_words_program(uint32_t ui32ProgramKey, uint32_t *pui32Src,
71 uint32_t *pui32Dst, uint32_t ui32NumWords)
72 {
73 //
74 // Use the new helper function to efficiently program the data in MRAM.
75 //
76
77 #ifndef AM_HAL_DISABLE_API_VALIDATION
78 //
79 // Check the Source to ensure proper location.
80 //
81 if ( ((uint32_t)pui32Src & 0xFF000000) == SRAM_BASEADDR )
82 {
83 //
84 // Check that the source buffer is within bounds (see errata ERR122)
85 //
86 if ( ((uint32_t)pui32Src + (ui32NumWords * 4)) > HLPRFNC_MAXSRC_ADDR )
87 {
88 return AM_HAL_STATUS_OUT_OF_RANGE;
89 }
90 }
91 #endif // AM_HAL_DISABLE_API_VALIDATION
92
93 if ( (uint32_t)pui32Dst <= AM_HAL_MRAM_LARGEST_VALID_ADDR )
94 {
95 //
96 // This helper function requires a word offset rather than an actual
97 // address. Since MRAM addresses start at 0x0, we can convert the addr
98 // into a word offset by simply dividing the destination address by 4.
99 //
100 pui32Dst = (uint32_t*)((uint32_t)pui32Dst / 4);
101 }
102
103 return g_am_hal_bootrom_helper.nv_program_main2(ui32ProgramKey, 1,
104 (uint32_t)pui32Src,
105 (uint32_t)pui32Dst,
106 ui32NumWords);
107 }
108
109 //*****************************************************************************
110 //
111 // This programs up to N words of the Main MRAM
112 //
113 //*****************************************************************************
114 int
am_hal_mram_main_program(uint32_t ui32ProgramKey,uint32_t * pui32Src,uint32_t * pui32Dst,uint32_t ui32NumWords)115 am_hal_mram_main_program(uint32_t ui32ProgramKey, uint32_t *pui32Src,
116 uint32_t *pui32Dst, uint32_t ui32NumWords)
117 {
118 //
119 // Check for pui32Dst & ui32NumWords
120 //
121 if (((uint32_t)pui32Dst & 0xf) || (ui32NumWords & 0x3))
122 {
123 return -1;
124 }
125
126 return am_hal_mram_main_words_program(ui32ProgramKey, pui32Src,
127 pui32Dst, ui32NumWords);
128 }
129
130 //*****************************************************************************
131 //
132 // This Fills up to N words of the Main MRAM
133 //
134 //*****************************************************************************
135 int
am_hal_mram_main_fill(uint32_t ui32ProgramKey,uint32_t ui32Value,uint32_t * pui32Dst,uint32_t ui32NumWords)136 am_hal_mram_main_fill(uint32_t ui32ProgramKey, uint32_t ui32Value,
137 uint32_t *pui32Dst, uint32_t ui32NumWords)
138 {
139 //
140 // Check for pui32Dst & ui32NumWords
141 //
142 if (((uint32_t)pui32Dst & 0xf) || (ui32NumWords & 0x3))
143 {
144 return -1;
145 }
146
147 //
148 // Use the new helper function to efficiently fill MRAM with a value.
149 //
150
151 if ( (uint32_t)pui32Dst <= AM_HAL_MRAM_LARGEST_VALID_ADDR )
152 {
153 //
154 // This helper function requires a word offset rather than an actual
155 // address. Since MRAM addresses start at 0x0, we can convert the addr
156 // into a word offset by simply dividing the destination address by 4.
157 //
158 pui32Dst = (uint32_t*)((uint32_t)pui32Dst / 4);
159 }
160
161 return g_am_hal_bootrom_helper.nv_program_main2(ui32ProgramKey, 0,
162 (uint32_t)ui32Value,
163 (uint32_t)pui32Dst,
164 ui32NumWords);
165 }
166
167 //*****************************************************************************
168 //
169 // This programs up to N words of the Main array on one MRAM.
170 //
171 //*****************************************************************************
172 int
am_hal_mram_info_program(uint32_t ui32InfoKey,uint32_t * pui32Src,uint32_t ui32Offset,uint32_t ui32NumWords)173 am_hal_mram_info_program(uint32_t ui32InfoKey, uint32_t *pui32Src,
174 uint32_t ui32Offset, uint32_t ui32NumWords)
175 {
176 int retval;
177
178 #ifndef AM_HAL_DISABLE_API_VALIDATION
179 //
180 // Check the Source to ensure proper location.
181 //
182 if ( ((uint32_t)pui32Src & 0xFF000000) == SRAM_BASEADDR )
183 {
184 //
185 // Check that the source buffer is within bounds (see errata ERR122)
186 //
187 if ( ((uint32_t)pui32Src + (ui32NumWords * 4)) > HLPRFNC_MAXSRC_ADDR )
188 {
189 return AM_HAL_STATUS_OUT_OF_RANGE;
190 }
191 }
192 #endif // AM_HAL_DISABLE_API_VALIDATION
193
194 MRAM_OVERRIDE();
195
196 retval = g_am_hal_bootrom_helper.nv_program_info_area(ui32InfoKey,
197 pui32Src, ui32Offset, ui32NumWords);
198
199 MRAM_REVERT();
200
201 return retval;
202 }
203
204 #ifdef INFO_ACCESS_WA
205
206 //*****************************************************************************
207 //
208 //! @brief This function erases main MRAM + customer INFO space
209 //!
210 //! @param ui32BrickKey - The Brick key.
211 //!
212 //! This function erases main MRAM and customer INFOinstance
213 //! even if the customer INFO space is programmed to not be erasable. This
214 //! function completely erases the MRAM main and info instance and wipes the
215 //! SRAM. Upon completion of the erasure operations, it does a POI (power on
216 //! initialization) reset.
217 //!
218 //! @note This function enforces 128 bit customer key lock. The caller needs to assert
219 //! the Recovery Lock using am_hal_security_set_key() providing appropriate key.
220 //! Otherwise, the function will fail. Therefore, always check for a return code.
221 //! If the function returns, a failure has occured.
222 //!
223 //! @return Does not return if successful. Returns failure code otherwise.
224 //! Failing return code indicates:
225 //! 0x00000001 ui32BrickKey is invalid.
226 //! 0x00000002 Recovery key lock not set.
227 //! Other values indicate Internal error.
228 //
229 //*****************************************************************************
230 int
am_hal_mram_recovery(uint32_t ui32BrickKey)231 am_hal_mram_recovery(uint32_t ui32BrickKey)
232 {
233 return g_am_hal_bootrom_helper.nv_recovery(ui32BrickKey);
234 }
235 #endif
236
237 //*****************************************************************************
238 //
239 // Read INFO data.
240 //
241 //*****************************************************************************
242 int
am_hal_mram_info_read(uint32_t ui32InfoSpace,uint32_t ui32WordOffset,uint32_t ui32NumWords,uint32_t * pui32Dst)243 am_hal_mram_info_read(uint32_t ui32InfoSpace,
244 uint32_t ui32WordOffset,
245 uint32_t ui32NumWords,
246 uint32_t *pui32Dst)
247 {
248 int retval = 0;
249 uint32_t ux;
250 uint32_t *pui32Info;
251
252 if ( ui32InfoSpace == 0 )
253 {
254 if ( (ui32WordOffset >= (AM_HAL_INFO0_SIZE_BYTES / 4)) || ((ui32WordOffset + ui32NumWords) > (AM_HAL_INFO0_SIZE_BYTES / 4)) )
255 {
256 return 2;
257 }
258 pui32Info = (uint32_t*)(AM_REG_INFO0_BASEADDR + (ui32WordOffset * 4));
259 }
260 else if ( ui32InfoSpace == 1 )
261 {
262 if ( (ui32WordOffset < (AM_HAL_INFO1_VISIBLE_OFFSET / 4)) || (ui32WordOffset >= (AM_HAL_INFO1_SIZE_BYTES / 4)) || ((ui32WordOffset + ui32NumWords) > (AM_HAL_INFO1_SIZE_BYTES / 4)) )
263 {
264 return 2;
265 }
266 pui32Info = (uint32_t*)(AM_REG_INFO1_BASEADDR + (ui32WordOffset * 4));
267 }
268 else
269 {
270 return 1;
271 }
272
273 #ifdef INFO_ACCESS_WA
274 MRAM_OVERRIDE();
275
276 //
277 // Start a critical section.
278 //
279 AM_CRITICAL_BEGIN
280
281 for (ux = 0; ux < ui32NumWords; ux++ )
282 {
283 // INFO read should use the util function - to ensure the code is not running from MRAM
284 *pui32Dst++ = am_hal_load_ui32(pui32Info++);
285 }
286
287 //
288 // End the critical section.
289 //
290 AM_CRITICAL_END
291
292 MRAM_REVERT();
293 #else
294 for (ux = 0; ux < ui32NumWords; ux++ )
295 {
296 *pui32Dst++ = AM_REGVAL(pui32Info++);
297 }
298 #endif
299
300 return retval;
301 }
302
303 //*****************************************************************************
304 //
305 // Initialize MRAM for DeepSleep.
306 //
307 //*****************************************************************************
308 int
am_hal_mram_ds_init(void)309 am_hal_mram_ds_init(void)
310 {
311 MRAM_RECOVER();
312 return 0;
313 }
314
315 //*****************************************************************************
316 //
317 // End Doxygen group.
318 //! @}
319 //
320 //*****************************************************************************
321