1 /***************************************************************************//**
2 * \file cy_efuse.c
3 * \version 2.30
4 *
5 * \brief
6 * Provides API implementation of the eFuse driver.
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright 2017-2020 Cypress Semiconductor Corporation
11 * SPDX-License-Identifier: Apache-2.0
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License");
14 * you may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *******************************************************************************/
25
26 #include "cy_device.h"
27
28 #if defined (CY_IP_MXEFUSE) && (CY_IP_MXEFUSE_VERSION <= 2)
29
30 #include "cy_efuse.h"
31 #include "cy_ipc_drv.h"
32
33 /** \cond INTERNAL */
34 #define CY_EFUSE_OPCODE_SUCCESS (0xA0000000UL) /**< The command completed with no errors */
35 #define CY_EFUSE_OPCODE_STS_Msk (0xF0000000UL) /**< The status mask of the SROM API return value */
36 #define CY_EFUSE_OPCODE_INV_PROT (0xF0000001UL) /**< The API is not available in the current protection state */
37 #define CY_EFUSE_OPCODE_INV_ADDR (0xF0000002UL) /**< An attempt to read byte from the out-of-bond or protected eFuse region */
38 #define CY_EFUSE_OPCODE_READ_FUSE_BYTE (0x03000000UL) /**< The SROM API opcode for Read fuse byte operation */
39 #define CY_EFUSE_OPCODE_OFFSET_Pos (8UL) /**< A fuse byte offset position in an opcode */
40 #define CY_EFUSE_OPCODE_DATA_Msk (0xFFUL) /**< The mask for extracting data from the SROM API return value */
41 #define CY_EFUSE_IPC_STRUCT (Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL)) /**< IPC structure to be used */
42 #define CY_EFUSE_IPC_NOTIFY_STRUCT0 (0x1UL << CY_IPC_INTR_SYSCALL1) /**< IPC notify bit for IPC0 structure (dedicated to System Call) */
43
44 /** \endcond */
45
46 #ifdef ENABLE_CM7_DATA_CACHE
47 CY_SECTION_SHAREDMEM
48 CY_ALIGN(32) static volatile uint32_t opcode = 0UL;
49 #else
50 static volatile uint32_t opcode;
51 #endif
52
53 static cy_en_efuse_status_t ProcessOpcode(void);
54
Cy_EFUSE_GetEfuseBit(uint32_t bitNum,bool * bitVal)55 cy_en_efuse_status_t Cy_EFUSE_GetEfuseBit(uint32_t bitNum, bool *bitVal)
56 {
57 cy_en_efuse_status_t result = CY_EFUSE_BAD_PARAM;
58
59 if (bitVal != NULL)
60 {
61 uint32_t offset = bitNum / CY_EFUSE_BITS_PER_BYTE;
62 uint8_t byteVal;
63 *bitVal = false;
64
65 /* Read the eFuse byte */
66 result = Cy_EFUSE_GetEfuseByte(offset, &byteVal);
67
68 if (result == CY_EFUSE_SUCCESS)
69 {
70 uint32_t bitPos = bitNum % CY_EFUSE_BITS_PER_BYTE;
71 /* Extract the bit from the byte */
72 *bitVal = (((byteVal >> bitPos) & 0x01U) != 0U);
73 }
74 }
75 return (result);
76 }
77
Cy_EFUSE_GetEfuseByte(uint32_t offset,uint8_t * byteVal)78 cy_en_efuse_status_t Cy_EFUSE_GetEfuseByte(uint32_t offset, uint8_t *byteVal)
79 {
80 cy_en_efuse_status_t result = CY_EFUSE_BAD_PARAM;
81 cy_en_ipcdrv_status_t retStatus;
82
83 if (byteVal != NULL)
84 {
85 /* Prepare opcode before calling the SROM API */
86 opcode = CY_EFUSE_OPCODE_READ_FUSE_BYTE | (offset << CY_EFUSE_OPCODE_OFFSET_Pos);
87
88 #ifdef ENABLE_CM7_DATA_CACHE
89 #if defined (CY_IP_M7CPUSS)
90 #if (CY_CPU_CORTEX_M7)
91 SCB_CleanDCache_by_Addr((uint32_t *)&opcode, (int32_t)sizeof(opcode));
92 #endif
93 #endif
94 #endif
95
96 retStatus = Cy_IPC_Drv_SendMsgPtr(CY_EFUSE_IPC_STRUCT, CY_EFUSE_IPC_NOTIFY_STRUCT0, (void*)&opcode);
97
98 /* Send the IPC message */
99 if (retStatus == CY_IPC_DRV_SUCCESS)
100 {
101 /* Wait until the IPC structure is locked */
102 while(Cy_IPC_Drv_IsLockAcquired(CY_EFUSE_IPC_STRUCT) != false)
103 {
104 }
105
106 #ifdef ENABLE_CM7_DATA_CACHE
107 #if defined (CY_IP_M7CPUSS)
108 #if (CY_CPU_CORTEX_M7)
109 SCB_InvalidateDCache_by_Addr((uint32_t *)&opcode, (int32_t)sizeof(opcode));
110 #endif
111 #endif
112 #endif
113
114 /* The result of the SROM API call is returned to the opcode variable */
115 if ((opcode & CY_EFUSE_OPCODE_STS_Msk) == CY_EFUSE_OPCODE_SUCCESS)
116 {
117 *byteVal = (uint8_t)(opcode & CY_EFUSE_OPCODE_DATA_Msk);
118 result = CY_EFUSE_SUCCESS;
119 }
120 else
121 {
122 result = ProcessOpcode();
123 *byteVal = 0U;
124 }
125 }
126 else
127 {
128 result = CY_EFUSE_IPC_BUSY;
129 }
130 }
131 return (result);
132 }
133
Cy_EFUSE_GetExternalStatus(void)134 uint32_t Cy_EFUSE_GetExternalStatus(void)
135 {
136 return (opcode);
137 }
138
139
140 /*******************************************************************************
141 * Function Name: ProcessOpcode
142 ****************************************************************************//**
143 *
144 * Converts System Call returns to the eFuse driver return defines. If
145 * an unknown error was returned, the error code can be accessed via the
146 * Cy_EFUSE_GetExternalStatus() function.
147 *
148 * \return
149 * \ref cy_en_efuse_status_t
150 *
151 *******************************************************************************/
ProcessOpcode(void)152 static cy_en_efuse_status_t ProcessOpcode(void)
153 {
154 cy_en_efuse_status_t result;
155
156 switch(opcode)
157 {
158 case CY_EFUSE_OPCODE_INV_PROT :
159 {
160 result = CY_EFUSE_INVALID_PROTECTION;
161 break;
162 }
163 case CY_EFUSE_OPCODE_INV_ADDR :
164 {
165 result = CY_EFUSE_INVALID_FUSE_ADDR;
166 break;
167 }
168 default :
169 {
170 result = CY_EFUSE_ERR_UNC;
171 break;
172 }
173 }
174
175 return (result);
176 }
177
178 #endif /* #ifdef (CY_IP_MXEFUSE) && (CY_IP_MXEFUSE_VERSION <= 2) */
179
180 /* [] END OF FILE */
181