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