1 //*****************************************************************************
2 //
3 //! @file am_util_id.c
4 //!
5 //! @brief Identification of the Ambiq Micro device.
6 //!
7 //! This module contains functions for run time identification of Ambiq Micro
8 //! devices.
9 //!
10 //! @addtogroup id ID - Identification
11 //! @ingroup utils
12 //! @{
13 //
14 //*****************************************************************************
15
16 //*****************************************************************************
17 //
18 // Copyright (c) 2024, Ambiq Micro, Inc.
19 // All rights reserved.
20 //
21 // Redistribution and use in source and binary forms, with or without
22 // modification, are permitted provided that the following conditions are met:
23 //
24 // 1. Redistributions of source code must retain the above copyright notice,
25 // this list of conditions and the following disclaimer.
26 //
27 // 2. Redistributions in binary form must reproduce the above copyright
28 // notice, this list of conditions and the following disclaimer in the
29 // documentation and/or other materials provided with the distribution.
30 //
31 // 3. Neither the name of the copyright holder nor the names of its
32 // contributors may be used to endorse or promote products derived from this
33 // software without specific prior written permission.
34 //
35 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
36 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
39 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
40 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
41 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
42 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
43 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
45 // POSSIBILITY OF SUCH DAMAGE.
46 //
47 // This is part of revision stable-c1f95ddf60 of the AmbiqSuite Development Package.
48 //
49 //*****************************************************************************
50 #include <stdint.h>
51 #include "am_util_id.h"
52
53 //*****************************************************************************
54 //
55 // Globals.
56 //
57 //*****************************************************************************
58 //
59 //! Strings for use with pui8VendorName.
60 //
61 #if defined(AM_ID_APOLLO)
62 static const uint8_t g_DeviceNameApollo[] = "Apollo";
63 #endif
64 #if defined(AM_ID_APOLLO2)
65 static const uint8_t g_DeviceNameApollo2[] = "Apollo2";
66 #endif
67 #if defined(AM_ID_APOLLO3)
68 static const uint8_t g_DeviceNameApollo3[] = "Apollo3 Blue";
69 #endif
70 #if defined(AM_ID_APOLLO3P)
71 static const uint8_t g_DeviceNameApollo3p[] = "Apollo3 Blue Plus";
72 #endif
73 #if defined(AM_ID_APOLLO4A)
74 static const uint8_t g_DeviceNameApollo4[] = "Apollo4 revA";
75 #endif
76 #if defined(AM_ID_APOLLO4B)
77 static const uint8_t g_DeviceNameApollo4b[] = "Apollo4b";
78 #endif
79 #if defined(AM_ID_APOLLO4P)
80 static const uint8_t g_DeviceNameApollo4p[] = "Apollo4 Plus";
81 static const uint8_t g_DeviceNameApollo4p_blue[] = "Apollo4 Blue Plus";
82 static const uint8_t g_PackageType[][4] = { "SIP", "SIP2", "BGA", "CSP" };
83 #endif
84 #if defined(AM_ID_APOLLO4L)
85 static const uint8_t g_DeviceNameApollo4l[] = "Apollo4 Lite";
86 #endif
87 #if defined(AM_ID_APOLLO5A)
88 static const uint8_t g_DeviceNameApollo5a[] = "Apollo5 revA";
89 #endif // AM_ID_APOLLO5A
90 #if defined(AM_ID_APOLLO5B)
91 static const uint8_t g_DeviceNameApollo5b[] = "Apollo5 revB";
92 #endif // AM_ID_APOLLO5B
93
94 static const uint8_t g_TempRange[][11] = { "Commercial", "Military", "Automotive", "Industrial" };
95 static const uint8_t g_ui8VendorNameAmbq[] = "AMBQ";
96 static const uint8_t g_ui8VendorNameUnknown[] = "????";
97 static const uint8_t g_ui8DeviceNameUnknown[] = "Unknown device";
98
99 #if !defined(AM_ID_APOLLO) && !defined(AM_ID_APOLLO2)
100 //*****************************************************************************
101 // Return the major version of the chip rev.
102 // Returns: 'A', 'B', 'C', ...
103 //*****************************************************************************
104 static uint32_t
revmaj_get(uint32_t ui32ChipRev)105 revmaj_get(uint32_t ui32ChipRev)
106 {
107 uint32_t ui32ret;
108
109 #ifdef _FLD2VAL
110 ui32ret = _FLD2VAL(MCUCTRL_CHIPREV_REVMAJ, ui32ChipRev);
111 #else
112 ui32ret = (ui32ChipRev & 0xF0) >> 4;
113 #endif
114
115 //
116 // Major revision is 1=A, 2=B, 3=C, ...
117 // Convert to the expected return value.
118 //
119 return ui32ret + 'A' - 1;
120
121 } // revmaj_get()
122 #endif
123
124 //*****************************************************************************
125 // Update the ID structure with the appropriate ChipRev letter.
126 // ui32minrevbase should be 0 for Apollo or Apollo2, 1 for Apollo3.
127 //*****************************************************************************
128 static void
chiprev_set(am_util_id_t * psIDDevice,uint32_t ui32minrevbase)129 chiprev_set(am_util_id_t *psIDDevice, uint32_t ui32minrevbase)
130 {
131 uint32_t ui32maj, ui32min;
132
133 ui32maj = ((psIDDevice->sMcuCtrlDevice.ui32ChipRev & 0xF0) >> 4);
134 psIDDevice->ui8ChipRevMaj = (uint8_t)('A' - 1 + ui32maj);
135
136 //
137 // For Apollo and Apollo2: rev0=0, rev1=1, ... (0-based)
138 // For Apollo3: rev0=1, rev1=2, ... (1-based)
139 //
140 ui32min = ((psIDDevice->sMcuCtrlDevice.ui32ChipRev & 0x0F) >> 0);
141 psIDDevice->ui8ChipRevMin = (uint8_t)('0' + ui32min - ui32minrevbase);
142
143 } // chiprev_set()
144
145 //*****************************************************************************
146 //
147 // Device identification.
148 //
149 //*****************************************************************************
150 uint32_t
am_util_id_device(am_util_id_t * psIDDevice)151 am_util_id_device(am_util_id_t *psIDDevice)
152 {
153 #if !defined(AM_ID_APOLLO) && !defined(AM_ID_APOLLO2)
154 uint32_t ui32ChipRev;
155 #endif
156 uint32_t ui32PN;
157
158 //
159 // Initialize to default as "unknown".
160 //
161 psIDDevice->ui32Device = AM_UTIL_ID_UNKNOWN;
162 psIDDevice->pui8DeviceName = g_ui8DeviceNameUnknown;
163 psIDDevice->pui8VendorName = g_ui8VendorNameUnknown;
164 psIDDevice->ui8ChipRevMaj = (uint8_t)'?';
165 psIDDevice->ui8ChipRevMin = (uint8_t)' ';
166
167 //
168 // Go get all the device (hardware) info from the HAL
169 //
170 #if defined(AM_PART_APOLLO3_API) || defined(AM_PART_APOLLO4_API) || defined(AM_PART_APOLLO5_API)
171 am_hal_mcuctrl_info_get(AM_HAL_MCUCTRL_INFO_DEVICEID, &psIDDevice->sMcuCtrlDevice);
172 am_hal_mcuctrl_info_get(AM_HAL_MCUCTRL_INFO_FEATURES_AVAIL, &psIDDevice->sMcuCtrlFeature);
173 #else
174 am_hal_mcuctrl_device_info_get(&psIDDevice->sMcuCtrlDevice);
175 #endif
176
177 //
178 // Device identification
179 //
180 ui32PN = psIDDevice->sMcuCtrlDevice.ui32ChipPN &
181 AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_PN_M;
182 #if !defined(AM_ID_APOLLO) && !defined(AM_ID_APOLLO2)
183 ui32ChipRev = psIDDevice->sMcuCtrlDevice.ui32ChipRev;
184 #endif
185
186 if ( ( psIDDevice->sMcuCtrlDevice.ui32VendorID ==
187 (('A' << 24) | ('M' << 16) | ('B' << 8) | ('Q' << 0)) ) )
188 {
189 //
190 // VENDORID is AMBQ. Set the manufacturer string pointer.
191 //
192 psIDDevice->pui8VendorName = g_ui8VendorNameAmbq;
193 }
194
195 #if defined(AM_ID_APOLLO)
196 //
197 // Apollo1 did not support VENDORID.
198 // Do a specific check from JEDEC values to verify Ambiq as the vendor.
199 //
200 if ( ((psIDDevice->sMcuCtrlDevice.ui32JedecCID == 0xB105100D) &&
201 (psIDDevice->sMcuCtrlDevice.ui32JedecJEPID == 0x0000009B) &&
202 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0xF00) == 0xE00)) )
203 {
204 //
205 // VENDORID is AMBQ. Set the manufacturer string pointer.
206 //
207 psIDDevice->pui8VendorName = g_ui8VendorNameAmbq;
208 }
209
210 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO ) &&
211 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0E0) )
212 {
213 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO;
214 psIDDevice->pui8DeviceName = g_DeviceNameApollo;
215 chiprev_set(psIDDevice, 0);
216 }
217 #endif // AM_ID_APOLLO
218
219 #if defined(AM_ID_APOLLO2)
220 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO2 ) &&
221 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0D0) )
222 {
223 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO2;
224 psIDDevice->pui8DeviceName = g_DeviceNameApollo2;
225 chiprev_set(psIDDevice, 0);
226 }
227 #endif // AM_ID_APOLLO2
228
229 #if defined(AM_ID_APOLLO3)
230 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO3 ) &&
231 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0C0) &&
232 ( revmaj_get(ui32ChipRev) <= 'B' ) )
233 {
234 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO3;
235 psIDDevice->pui8DeviceName = g_DeviceNameApollo3;
236 chiprev_set(psIDDevice, 1);
237 }
238 #endif // AM_ID_APOLLO3
239
240 #if defined(AM_ID_APOLLO3P)
241 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO3P) &&
242 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0C0) &&
243 ( revmaj_get(ui32ChipRev) == 'C' ) )
244 {
245 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO3P;
246 psIDDevice->pui8DeviceName = g_DeviceNameApollo3p;
247 chiprev_set(psIDDevice, 1);
248 }
249 #endif // AM_ID_APOLLO3P
250
251 #if defined(AM_ID_APOLLO4A)
252 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO4) &&
253 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0B0) &&
254 ( revmaj_get(ui32ChipRev) == 'A' ) )
255 {
256 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO4;
257 psIDDevice->pui8DeviceName = g_DeviceNameApollo4;
258 chiprev_set(psIDDevice, 1);
259 }
260 #endif // AM_ID_APOLLO4A
261
262 #if defined(AM_ID_APOLLO4B)
263 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO4) &&
264 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0B0) &&
265 ( revmaj_get(ui32ChipRev) == 'B' ) )
266 {
267 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO4;
268 psIDDevice->pui8DeviceName = g_DeviceNameApollo4b;
269 chiprev_set(psIDDevice, 1);
270 }
271 #endif // AM_ID_APOLLO4B
272
273 #if defined(AM_ID_APOLLO4P)
274 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO4) &&
275 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0B0) &&
276 ( revmaj_get(ui32ChipRev) == 'C' ) )
277 {
278 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO4P;
279 if ( ((psIDDevice->sMcuCtrlDevice.ui32ChipPN & 0xc0) >> 6) >= 2 )
280 {
281 psIDDevice->pui8DeviceName = g_DeviceNameApollo4p;
282 }
283 else
284 {
285 psIDDevice->pui8DeviceName = g_DeviceNameApollo4p_blue;
286 }
287 chiprev_set(psIDDevice, 1);
288 }
289 #endif // AM_ID_APOLLO4P
290
291 #if defined(AM_ID_APOLLO4L)
292 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO4L) &&
293 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0B0) &&
294 ( revmaj_get(ui32ChipRev) == 'A' ) )
295 {
296 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO4L;
297 psIDDevice->pui8DeviceName = g_DeviceNameApollo4l;
298 chiprev_set(psIDDevice, 1);
299 }
300 #endif // AM_ID_APOLLO4L
301
302 #if defined(AM_ID_APOLLO5A)
303 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO5A) &&
304 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0FF) == 0x0D2) &&
305 ( revmaj_get(ui32ChipRev) == 'A' ) )
306 {
307 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO5A;
308 psIDDevice->pui8DeviceName = g_DeviceNameApollo5a;
309 chiprev_set(psIDDevice, 1);
310 }
311 #endif // AM_ID_APOLLO5A
312
313 #if defined(AM_ID_APOLLO5B)
314 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO5B) &&
315 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0FF) == 0x0D2) &&
316 ( revmaj_get(ui32ChipRev) == 'B' ) )
317 {
318 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO5B;
319 psIDDevice->pui8DeviceName = g_DeviceNameApollo5b;
320 chiprev_set(psIDDevice, 1);
321 }
322 #endif // AM_ID_APOLLO5B
323
324 //
325 // This section defines the package type
326 //
327 // currently this is only defined for the Apollo4 Plus / Blue Plus
328 //
329 #if defined(AM_PART_APOLLO4P)
330 psIDDevice->pui8PackageType = g_PackageType[((psIDDevice->sMcuCtrlDevice.ui32ChipPN & 0xC0) >> 6)];
331 #else
332 psIDDevice->pui8PackageType = NULL;
333 #endif
334
335 psIDDevice->pui8TempRange = g_TempRange[((psIDDevice->sMcuCtrlDevice.ui32ChipPN & 0x06) >> 1)];
336
337 return psIDDevice->ui32Device;
338 }
339
340 //*****************************************************************************
341 //
342 // End Doxygen group.
343 //! @}
344 //
345 //*****************************************************************************
346
347