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