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) 2023, 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 release_sdk_4_4_0-3c5977e664 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
88 static const uint8_t g_TempRange[][11] = { "Commercial", "Military", "Automotive", "Industrial" };
89 static const uint8_t g_ui8VendorNameAmbq[] = "AMBQ";
90 static const uint8_t g_ui8VendorNameUnknown[] = "????";
91 static const uint8_t g_ui8DeviceNameUnknown[] = "Unknown device";
92
93 #if !defined(AM_ID_APOLLO) && !defined(AM_ID_APOLLO2)
94 //*****************************************************************************
95 // Return the major version of the chip rev.
96 // Returns: 'A', 'B', 'C', ...
97 //*****************************************************************************
98 static uint32_t
revmaj_get(uint32_t ui32ChipRev)99 revmaj_get(uint32_t ui32ChipRev)
100 {
101 uint32_t ui32ret;
102
103 #ifdef _FLD2VAL
104 ui32ret = _FLD2VAL(MCUCTRL_CHIPREV_REVMAJ, ui32ChipRev);
105 #else
106 ui32ret = (ui32ChipRev & 0xF0) >> 4;
107 #endif
108
109 //
110 // Major revision is 1=A, 2=B, 3=C, ...
111 // Convert to the expected return value.
112 //
113 return ui32ret + 'A' - 1;
114
115 } // revmaj_get()
116 #endif
117
118 //*****************************************************************************
119 // Update the ID structure with the appropriate ChipRev letter.
120 // ui32minrevbase should be 0 for Apollo or Apollo2, 1 for Apollo3.
121 //*****************************************************************************
122 static void
chiprev_set(am_util_id_t * psIDDevice,uint32_t ui32minrevbase)123 chiprev_set(am_util_id_t *psIDDevice, uint32_t ui32minrevbase)
124 {
125 uint32_t ui32maj, ui32min;
126
127 ui32maj = ((psIDDevice->sMcuCtrlDevice.ui32ChipRev & 0xF0) >> 4);
128 psIDDevice->ui8ChipRevMaj = (uint8_t)('A' - 1 + ui32maj);
129
130 //
131 // For Apollo and Apollo2: rev0=0, rev1=1, ... (0-based)
132 // For Apollo3: rev0=1, rev1=2, ... (1-based)
133 //
134 ui32min = ((psIDDevice->sMcuCtrlDevice.ui32ChipRev & 0x0F) >> 0);
135 psIDDevice->ui8ChipRevMin = (uint8_t)('0' + ui32min - ui32minrevbase);
136
137 } // chiprev_set()
138
139 //*****************************************************************************
140 //
141 // Device identification.
142 //
143 //*****************************************************************************
144 uint32_t
am_util_id_device(am_util_id_t * psIDDevice)145 am_util_id_device(am_util_id_t *psIDDevice)
146 {
147 #if !defined(AM_ID_APOLLO) && !defined(AM_ID_APOLLO2)
148 uint32_t ui32ChipRev;
149 #endif
150 uint32_t ui32PN;
151
152 //
153 // Initialize to default as "unknown".
154 //
155 psIDDevice->ui32Device = AM_UTIL_ID_UNKNOWN;
156 psIDDevice->pui8DeviceName = g_ui8DeviceNameUnknown;
157 psIDDevice->pui8VendorName = g_ui8VendorNameUnknown;
158 psIDDevice->ui8ChipRevMaj = (uint8_t)'?';
159 psIDDevice->ui8ChipRevMin = (uint8_t)' ';
160
161 //
162 // Go get all the device (hardware) info from the HAL
163 //
164 #if AM_APOLLO3_MCUCTRL
165 am_hal_mcuctrl_info_get(AM_HAL_MCUCTRL_INFO_DEVICEID, &psIDDevice->sMcuCtrlDevice);
166 am_hal_mcuctrl_info_get(AM_HAL_MCUCTRL_INFO_FEATURES_AVAIL, &psIDDevice->sMcuCtrlFeature);
167 #else // AM_APOLLO3_MCUCTRL
168 am_hal_mcuctrl_device_info_get(&psIDDevice->sMcuCtrlDevice);
169 #endif // AM_APOLLO3_MCUCTRL
170
171 //
172 // Device identification
173 //
174 ui32PN = psIDDevice->sMcuCtrlDevice.ui32ChipPN &
175 AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_PN_M;
176 #if !defined(AM_ID_APOLLO) && !defined(AM_ID_APOLLO2)
177 ui32ChipRev = psIDDevice->sMcuCtrlDevice.ui32ChipRev;
178 #endif
179
180 if ( ( psIDDevice->sMcuCtrlDevice.ui32VendorID ==
181 (('A' << 24) | ('M' << 16) | ('B' << 8) | ('Q' << 0)) ) )
182 {
183 //
184 // VENDORID is AMBQ. Set the manufacturer string pointer.
185 //
186 psIDDevice->pui8VendorName = g_ui8VendorNameAmbq;
187 }
188
189 #if defined(AM_ID_APOLLO)
190 //
191 // Apollo1 did not support VENDORID.
192 // Do a specific check from JEDEC values to verify Ambiq as the vendor.
193 //
194 if ( ((psIDDevice->sMcuCtrlDevice.ui32JedecCID == 0xB105100D) &&
195 (psIDDevice->sMcuCtrlDevice.ui32JedecJEPID == 0x0000009B) &&
196 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0xF00) == 0xE00)) )
197 {
198 //
199 // VENDORID is AMBQ. Set the manufacturer string pointer.
200 //
201 psIDDevice->pui8VendorName = g_ui8VendorNameAmbq;
202 }
203
204 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO ) &&
205 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0E0) )
206 {
207 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO;
208 psIDDevice->pui8DeviceName = g_DeviceNameApollo;
209 chiprev_set(psIDDevice, 0);
210 }
211 #endif // AM_ID_APOLLO
212
213 #if defined(AM_ID_APOLLO2)
214 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO2 ) &&
215 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0D0) )
216 {
217 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO2;
218 psIDDevice->pui8DeviceName = g_DeviceNameApollo2;
219 chiprev_set(psIDDevice, 0);
220 }
221 #endif // AM_ID_APOLLO2
222
223 #if defined(AM_ID_APOLLO3)
224 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO3 ) &&
225 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0C0) &&
226 ( revmaj_get(ui32ChipRev) <= 'B' ) )
227 {
228 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO3;
229 psIDDevice->pui8DeviceName = g_DeviceNameApollo3;
230 chiprev_set(psIDDevice, 1);
231 }
232 #endif // AM_ID_APOLLO3
233
234 #if defined(AM_ID_APOLLO3P)
235 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO3P) &&
236 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0C0) &&
237 ( revmaj_get(ui32ChipRev) == 'C' ) )
238 {
239 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO3P;
240 psIDDevice->pui8DeviceName = g_DeviceNameApollo3p;
241 chiprev_set(psIDDevice, 1);
242 }
243 #endif // AM_ID_APOLLO3P
244
245 #if defined(AM_ID_APOLLO4A)
246 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO4) &&
247 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0B0) &&
248 ( revmaj_get(ui32ChipRev) == 'A' ) )
249 {
250 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO4;
251 psIDDevice->pui8DeviceName = g_DeviceNameApollo4;
252 chiprev_set(psIDDevice, 1);
253 }
254 #endif // AM_ID_APOLLO4A
255
256 #if defined(AM_ID_APOLLO4B)
257 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO4) &&
258 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0B0) &&
259 ( revmaj_get(ui32ChipRev) == 'B' ) )
260 {
261 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO4;
262 psIDDevice->pui8DeviceName = g_DeviceNameApollo4b;
263 chiprev_set(psIDDevice, 1);
264 }
265 #endif // AM_ID_APOLLO4B
266
267 #if defined(AM_ID_APOLLO4P)
268 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO4) &&
269 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0B0) &&
270 ( revmaj_get(ui32ChipRev) == 'C' ) )
271 {
272 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO4P;
273 if ( ((psIDDevice->sMcuCtrlDevice.ui32ChipPN & 0xc0) >> 6) >= 2 )
274 {
275 psIDDevice->pui8DeviceName = g_DeviceNameApollo4p;
276 }
277 else
278 {
279 psIDDevice->pui8DeviceName = g_DeviceNameApollo4p_blue;
280 }
281 chiprev_set(psIDDevice, 1);
282 }
283 #endif // AM_ID_APOLLO4P
284
285 #if defined(AM_ID_APOLLO4L)
286 if ( ( ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLO4L) &&
287 ((psIDDevice->sMcuCtrlDevice.ui32JedecPN & 0x0F0) == 0x0B0) &&
288 ( revmaj_get(ui32ChipRev) == 'A' ) )
289 {
290 psIDDevice->ui32Device = AM_UTIL_ID_APOLLO4L;
291 psIDDevice->pui8DeviceName = g_DeviceNameApollo4l;
292 chiprev_set(psIDDevice, 1);
293 }
294 #endif // AM_ID_APOLLO4L
295
296
297 //
298 // This section defines the package type
299 //
300 // currently this is only defined for the Apollo4 Plus / Blue Plus
301 //
302 #if defined(AM_PART_APOLLO4P)
303 psIDDevice->pui8PackageType = g_PackageType[((psIDDevice->sMcuCtrlDevice.ui32ChipPN & 0xC0) >> 6)];
304 #else
305 psIDDevice->pui8PackageType = NULL;
306 #endif
307
308 psIDDevice->pui8TempRange = g_TempRange[((psIDDevice->sMcuCtrlDevice.ui32ChipPN & 0x06) >> 1)];
309
310 return psIDDevice->ui32Device;
311 }
312
313 //*****************************************************************************
314 //
315 // End Doxygen group.
316 //! @}
317 //
318 //*****************************************************************************
319
320