1 /*
2 * Copyright 2022 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include "fsl_silicon_id_soc.h"
8
9 #if defined(MIMX8ML8_cm7_SERIES) || defined(MIMX8ML6_cm7_SERIES) || defined(MIMX8ML4_cm7_SERIES) || \
10 defined(MIMX8ML3_cm7_SERIES)
11 #define OCOTP_UNIQUE_ID_ADDR_OFFSET (0x2U)
12 #else
13 #define OCOTP_UNIQUE_ID_ADDR_OFFSET (0x1U)
14 #endif
15
SILICONID_OcotpReadFuse(OCOTP_Type * base,uint32_t address,uint32_t * data)16 static status_t SILICONID_OcotpReadFuse(OCOTP_Type *base, uint32_t address, uint32_t *data)
17 {
18 /* Make sure the OCOTP is ready, Overlapped accesses are not supported by the controller. */
19 while (OCOTP_HW_OCOTP_CTRL_BUSY_MASK == (base->HW_OCOTP_CTRL & OCOTP_HW_OCOTP_CTRL_BUSY_MASK))
20 {
21 }
22
23 /* If ERROR bit was set, clear access error status bit. */
24 if (OCOTP_HW_OCOTP_CTRL_ERROR_MASK == (base->HW_OCOTP_CTRL & OCOTP_HW_OCOTP_CTRL_ERROR_MASK))
25 {
26 base->HW_OCOTP_CTRL_CLR = OCOTP_HW_OCOTP_CTRL_CLR_ERROR_MASK;
27 }
28
29 /* Write requested address to register. */
30 base->HW_OCOTP_CTRL_CLR = OCOTP_HW_OCOTP_CTRL_CLR_ADDR_MASK;
31 base->HW_OCOTP_CTRL_SET = OCOTP_HW_OCOTP_CTRL_SET_ADDR(address);
32 base->HW_OCOTP_READ_CTRL |= OCOTP_HW_OCOTP_READ_CTRL_READ_FUSE_MASK;
33
34 /* Wait for busy bit is cleared, and no error occurred on controller. */
35 while (OCOTP_HW_OCOTP_CTRL_BUSY_MASK == (base->HW_OCOTP_CTRL & OCOTP_HW_OCOTP_CTRL_BUSY_MASK))
36 {
37 }
38
39 /* If ERROR bit was set, this may be mean that the accsee to the register was wrong. */
40 if (OCOTP_HW_OCOTP_CTRL_ERROR_MASK == (base->HW_OCOTP_CTRL & OCOTP_HW_OCOTP_CTRL_ERROR_MASK))
41 {
42 /* Clear access error status bit. */
43 base->HW_OCOTP_CTRL_CLR = OCOTP_HW_OCOTP_CTRL_CLR_ERROR_MASK;
44
45 return kStatus_Fail;
46 }
47 *data = base->HW_OCOTP_READ_FUSE_DATA;
48 return kStatus_Success;
49 }
50
SILICONID_ReadUniqueID(uint8_t * siliconId,uint32_t * idLen)51 status_t SILICONID_ReadUniqueID(uint8_t *siliconId, uint32_t *idLen)
52 {
53 status_t result;
54 uint32_t readBytes = *idLen;
55 uint8_t uid[8];
56
57 result = SILICONID_OcotpReadFuse(OCOTP, OCOTP_UNIQUE_ID_ADDR_OFFSET, (uint32_t *)(uintptr_t)&uid[0]);
58 if (result != kStatus_Success)
59 {
60 *idLen = 0;
61 return result;
62 }
63
64 result = SILICONID_OcotpReadFuse(OCOTP, OCOTP_UNIQUE_ID_ADDR_OFFSET + 1U, (uint32_t *)(uintptr_t)&uid[4]);
65 if (result != kStatus_Success)
66 {
67 *idLen = 0;
68 return result;
69 }
70
71 readBytes = (readBytes > 8U) ? 8U : readBytes;
72 (void)memcpy((void *)&siliconId[0], (void *)&uid[0], readBytes);
73 *idLen = readBytes;
74
75 return kStatus_Success;
76 }
77