1 /***************************************************************************//**
2 * \file cy_efuse_v3.c
3 * \version 2.40
4 *
5 * \brief
6 * Provides API implementation of the eFuse version_3 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 >= 3)
29 
30 /*****************************************************************************/
31 /* Include files                                                             */
32 /*****************************************************************************/
33 #include "cy_efuse.h"
34 /*****************************************************************************/
35 /* Local pre-processor symbols/macros ('#define')                            */
36 /*****************************************************************************/
37 /** \cond INTERNAL */
38 #define EFUSE_MACRO_NUM             (EFUSE_EFUSE_NR)
39 #define EFUSE_MACRO_SIZE            (32UL)
40 #define EFUSE_SIZE                  (EFUSE_MACRO_SIZE * EFUSE_MACRO_NUM)
41 #define CY_EFUSE_WRITE_TIMEOUT_US   (10UL)
42 /** \endcond */
43 
44 /*****************************************************************************/
45 /* Global variable definitions (declared in header file with 'extern')       */
46 /*****************************************************************************/
47 
48 
49 /*****************************************************************************/
50 /* Local type definitions ('typedef')                                        */
51 /*****************************************************************************/
52 
53 
54 /*****************************************************************************/
55 /* Local variable definitions ('static')                                     */
56 /*****************************************************************************/
57 
58 
59 /*****************************************************************************/
60 /* Local function prototypes ('static')                                      */
61 /*****************************************************************************/
62 
63 /*****************************************************************************/
64 /* Function implementation - global ('extern') and local ('static')          */
65 /*****************************************************************************/
66 /**
67  *****************************************************************************
68  ** Cy_EFUSE_Enable
69  ** Enables the EFUSE block.
70  *****************************************************************************/
Cy_EFUSE_Enable(EFUSE_Type * base)71 void Cy_EFUSE_Enable(EFUSE_Type *base)
72 {
73     EFUSE_CTL(base) = EFUSE_CTL_ENABLED_Msk;
74 }
75 
76 /**
77  *****************************************************************************
78  ** Cy_EFUSE_Disable
79  ** Disables the EFUSE block. All non-retention registers (command and status
80  ** registers) are reset to their default values when the IP is disabled.
81  *****************************************************************************/
Cy_EFUSE_Disable(EFUSE_Type * base)82 void Cy_EFUSE_Disable(EFUSE_Type *base)
83 {
84     EFUSE_CTL(base) = 0UL;
85 }
86 
87 /**
88  *****************************************************************************
89  ** Cy_EFUSE_IsEnabled
90  ** Checks if EFUSE block is enabled or not.
91  *****************************************************************************/
Cy_EFUSE_IsEnabled(EFUSE_Type * base)92 bool Cy_EFUSE_IsEnabled(EFUSE_Type *base)
93 {
94     return (0U != _FLD2VAL(EFUSE_CTL_ENABLED, EFUSE_CTL(base)));
95 }
96 
97 
98 /**
99  *****************************************************************************
100  ** Cy_EFUSE_Init
101  ** This function enables the EFUSE block and initializes the registers with
102  ** the default values.
103  *****************************************************************************/
Cy_EFUSE_Init(EFUSE_Type * base)104 cy_en_efuse_status_t Cy_EFUSE_Init(EFUSE_Type *base)
105 {
106     /* Input parameter verification */
107     if (NULL == base)
108     {
109         return CY_EFUSE_BAD_PARAM;
110     }
111     Cy_EFUSE_Disable(base);
112     Cy_EFUSE_Enable(base);
113 
114     return CY_EFUSE_SUCCESS;
115 }
116 
117 /**
118  *****************************************************************************
119  ** Cy_EFUSE_DeInit
120  ** Disables the EFUSE block. All non-retention registers (command and status
121  ** registers) are reset to their default values when the IP is disabled.
122  *****************************************************************************/
Cy_EFUSE_DeInit(EFUSE_Type * base)123 void Cy_EFUSE_DeInit(EFUSE_Type *base)
124 {
125     Cy_EFUSE_Disable(base);
126 }
127 
128 /**
129  *****************************************************************************
130  ** Cy_EFUSE_WriteBit
131  ** Writes a bit to EFUSE by blowing a fuse, so this function is able to write
132  ** 1s only. Before write operations you must call \ref Cy_EFUSE_Init().
133  ** It is recommended to disable the block when not using it.
134  ** Call \ref Cy_EFUSE_Disable() to disable the EFUSE block.
135  *****************************************************************************/
Cy_EFUSE_WriteBit(EFUSE_Type * base,uint32_t bitPos,uint32_t offset)136 cy_en_efuse_status_t Cy_EFUSE_WriteBit(EFUSE_Type *base, uint32_t bitPos, uint32_t offset)
137 {
138     if((offset > EFUSE_SIZE) || (bitPos > CY_EFUSE_BITS_PER_BYTE))
139     {
140         return CY_EFUSE_BAD_PARAM;
141     }
142 
143     cy_en_efuse_status_t ret = CY_EFUSE_WRITE_BUSY;
144     uint32_t timeout = CY_EFUSE_WRITE_TIMEOUT_US;
145 
146     /* Check whether EFUSE is busy or not. If the sequencer is busy, wait for a 10us */
147     while ((0UL != (EFUSE_CMD(base) & EFUSE_CMD_START_Msk)) && (0UL < timeout))
148     {
149         Cy_SysLib_DelayUs(1U);
150         --timeout;
151     }
152 
153     if (0UL == (EFUSE_CMD(base) & EFUSE_CMD_START_Msk))
154     {
155         uint8_t readByte = 0;
156         /* NOTE: This only supports 4 EFUSE macros */
157         uint32_t byteAddr  = offset / EFUSE_MACRO_NUM;
158         uint32_t macroAddr = offset % EFUSE_MACRO_NUM;
159         EFUSE_CMD(base) = _VAL2FLD(EFUSE_CMD_BIT_DATA, 1UL)         | /* Bit data must be 1 to blow fuse */
160                           _VAL2FLD(EFUSE_CMD_BIT_ADDR, bitPos)      | /* Bit position within byte */
161                           _VAL2FLD(EFUSE_CMD_BYTE_ADDR, byteAddr)   | /* Byte address within EFUSE macro */
162                           _VAL2FLD(EFUSE_CMD_MACRO_ADDR, macroAddr) | /* EFUSE macro number */
163                           EFUSE_CMD_START_Msk;
164 
165         /* Wait for program access to complete */
166         timeout = CY_EFUSE_WRITE_TIMEOUT_US;
167         while ((0UL != (EFUSE_CMD(base) & EFUSE_CMD_START_Msk)) && (0UL < timeout))
168         {
169             Cy_SysLib_DelayUs(1U);
170             --timeout;
171         }
172 
173         if(0UL == timeout)
174         {
175             /* The program access is not completed */
176             return CY_EFUSE_WRITE_TIMEOUT_ERROR;
177         }
178 
179         /* This delay is required by the IP to operate at 48MHz(clk_sys) as suggested in the CDT:363011
180            The delay value will later be updated based on the design team recommendation. */
181         Cy_SysLib_DelayUs(100U);
182 
183         /* Check whether the program operation succeeded */
184         (void)Cy_EFUSE_ReadByte(base, &readByte, offset);
185         ret = (0UL != (readByte & (1UL << bitPos))) ? CY_EFUSE_SUCCESS : CY_EFUSE_WRITE_ERROR;
186     }
187 
188     return ret;
189 }
190 
191 /**
192  *****************************************************************************
193  ** Cy_EFUSE_WriteByte
194  ** Writes one byte.
195  ** Before write operations you must call \ref Cy_EFUSE_Init().
196  ** It is recommended to disable the block when not using it.
197  ** Call \ref Cy_EFUSE_Disable() to disable the EFUSE block.
198  *****************************************************************************/
Cy_EFUSE_WriteByte(EFUSE_Type * base,uint32_t src,uint32_t offset)199 cy_en_efuse_status_t Cy_EFUSE_WriteByte(EFUSE_Type *base, uint32_t src, uint32_t offset)
200 {
201     cy_en_efuse_status_t ret = CY_EFUSE_BAD_PARAM;
202 
203     if ((offset < EFUSE_SIZE) && (src <= 0xFFUL))
204     {
205         uint32_t bitPos = 0UL;
206         /* Clear the src bits that are already set */
207         uint8_t readByte;
208         /* No error check since the function parameters are already checked */
209         (void)Cy_EFUSE_ReadByte(base, &readByte, offset);
210         src &= (~((uint32_t)readByte));
211 
212         ret = CY_EFUSE_SUCCESS;
213         while ((0U != src) && (CY_EFUSE_SUCCESS == ret))
214         {
215             if (0UL != (src & 0x01UL))
216             {
217                 ret = Cy_EFUSE_WriteBit(base, bitPos, offset);
218             }
219             src >>= 1UL;
220             ++bitPos;
221         }
222     }
223     return ret;
224 }
225 
226 /**
227  *****************************************************************************
228  ** Cy_EFUSE_WriteWord
229  ** Writes every bit set in src that was not already programmed.
230  ** Before write operations you must call \ref Cy_EFUSE_Init().
231  ** It is recommended to disable the block when not using it.
232  ** Call \ref Cy_EFUSE_Disable() to disable the EFUSE block.
233  *****************************************************************************/
Cy_EFUSE_WriteWord(EFUSE_Type * base,uint32_t src,uint32_t offset)234 cy_en_efuse_status_t Cy_EFUSE_WriteWord(EFUSE_Type *base, uint32_t src, uint32_t offset)
235 {
236     cy_en_efuse_status_t ret = CY_EFUSE_BAD_PARAM;
237 
238     if ((offset < EFUSE_SIZE) && (0U == offset % 4U))
239     {
240         /* Clear the src bits that are already set */
241         uint32_t readWord = 0UL;
242         /* No error check since the function parameters are already checked */
243         (void)Cy_EFUSE_ReadWord(base, &readWord, offset);
244         src &= (uint32_t)~readWord;
245 
246         /* Perform a sequence of byte writes to write a word */
247         ret = CY_EFUSE_SUCCESS;
248         while ((0U != src) && (CY_EFUSE_SUCCESS == ret))
249         {
250             uint32_t val = src & 0xFFUL;
251             if (0UL != val)
252             {
253                 ret = Cy_EFUSE_WriteByte(base, val, offset);
254             }
255             src >>= 8UL;
256             ++offset;
257         }
258     }
259     return ret;
260 }
261 
262 /**
263  *****************************************************************************
264  ** Cy_EFUSE_WriteWordArray
265  ** Writes the values of num 32-bit words from the location pointed to by src
266  ** to the EFUSE location pointed to by offset.
267  *****************************************************************************/
Cy_EFUSE_WriteWordArray(EFUSE_Type * base,const uint32_t * src,uint32_t offset,uint32_t num)268 cy_en_efuse_status_t Cy_EFUSE_WriteWordArray(EFUSE_Type *base, const uint32_t *src, uint32_t offset, uint32_t num)
269 {
270     cy_en_efuse_status_t ret = CY_EFUSE_BAD_PARAM;
271 
272     if ((offset < EFUSE_SIZE) && ((EFUSE_SIZE - offset) >= (num * sizeof(uint32_t))))
273     {
274         ret = CY_EFUSE_SUCCESS;
275         for(; 0UL != num; --num)
276         {
277             if (0UL != *src)
278             {
279                 ret = Cy_EFUSE_WriteWord(base, *src, offset);
280             }
281             if(CY_EFUSE_SUCCESS != ret)
282             {
283                 return ret;
284             }
285             ++src;
286             offset += 4UL; /* One 4-byte word is written at a time */
287         }
288     }
289     return ret;
290 }
291 
292 /**
293  *****************************************************************************
294  ** Cy_EFUSE_ReadBit
295  ** Reads a bit from EFUSE.
296  ** Before read operations you must call \ref Cy_EFUSE_Init().
297  ** It is recommended to disable the block when not using it.
298  ** Call \ref Cy_EFUSE_Disable() to disable the EFUSE block.
299  *****************************************************************************/
Cy_EFUSE_ReadBit(EFUSE_Type * base,uint8_t * dst,uint32_t bitPos,uint32_t offset)300 cy_en_efuse_status_t Cy_EFUSE_ReadBit(EFUSE_Type *base, uint8_t *dst, uint32_t bitPos, uint32_t offset)
301 {
302     cy_en_efuse_status_t ret = CY_EFUSE_BAD_PARAM;
303     if ((offset < EFUSE_SIZE) && (bitPos < CY_EFUSE_BITS_PER_BYTE))
304     {
305         uint8_t byte;
306 
307         /* No error check since the function parameters are already checked */
308         (void) Cy_EFUSE_ReadByte(base, &byte, offset);
309 
310         /* Extract the bit using the bit position value */
311         *dst = (byte >> bitPos) & 0x01U;
312         ret = CY_EFUSE_SUCCESS;
313     }
314     return ret;
315 }
316 
317 /**
318  *****************************************************************************
319  ** Cy_EFUSE_ReadByte
320  ** Reads byte from EFUSE.
321  ** Before read operations you must call \ref Cy_EFUSE_Init().
322  ** It is recommended to disable the block when not using it.
323  ** Call \ref Cy_EFUSE_Disable() to disable the EFUSE block.
324  *****************************************************************************/
Cy_EFUSE_ReadByte(EFUSE_Type * base,uint8_t * dst,uint32_t offset)325 cy_en_efuse_status_t Cy_EFUSE_ReadByte(EFUSE_Type *base, uint8_t *dst, uint32_t offset)
326 {
327     cy_en_efuse_status_t ret = CY_EFUSE_BAD_PARAM;
328     if (offset < EFUSE_SIZE)
329     {
330         uint32_t word = 0UL;
331 
332         /* Byte number within a 4-byte word */
333         uint32_t byteNum = offset & 3UL;
334 
335         /* Offset must be 4-byte aligned for addressing MMIO space */
336         offset &= ~3UL;
337 
338         /* No error check since the function parameters are already checked */
339         (void) Cy_EFUSE_ReadWord(base, &word, offset);
340 
341         /* Extract the byte using the byte number */
342         *dst = (uint8_t)(word >> (byteNum * 8UL));
343         ret = CY_EFUSE_SUCCESS;
344     }
345     return ret;
346 }
347 
348 /**
349  *****************************************************************************
350  ** Cy_EFUSE_ReadWord
351  ** Reads a 32-bit word from EFUSE.
352  ** Before read operations you must call \ref Cy_EFUSE_Init().
353  ** It is recommended to disable the block when not using it.
354  ** Call \ref Cy_EFUSE_Disable() to disable the EFUSE block.
355  *****************************************************************************/
Cy_EFUSE_ReadWord(EFUSE_Type * base,uint32_t * dst,uint32_t offset)356 cy_en_efuse_status_t Cy_EFUSE_ReadWord(EFUSE_Type *base, uint32_t *dst, uint32_t offset)
357 {
358     /* Suppress a compiler warning about unused variables */
359     (void) base;
360     cy_en_efuse_status_t ret = CY_EFUSE_BAD_PARAM;
361     if ((offset < EFUSE_SIZE) && (0U == offset % 4U))
362     {
363         *dst = CY_GET_REG32(CY_EFUSE_BASE + offset);
364         ret = CY_EFUSE_SUCCESS;
365     }
366     return ret;
367 }
368 
369 /**
370  *****************************************************************************
371  ** Cy_EFUSE_ReadWordArray
372  ** Reads an array of 32-bit words from EFUSE.
373  ** Before read operations you must call \ref Cy_EFUSE_Init().
374  ** It is recommended to disable the block when not using it.
375  ** Call \ref Cy_EFUSE_Disable() to disable the EFUSE block.
376  *****************************************************************************/
Cy_EFUSE_ReadWordArray(EFUSE_Type * base,uint32_t * dst,uint32_t offset,uint32_t num)377 cy_en_efuse_status_t Cy_EFUSE_ReadWordArray(EFUSE_Type *base, uint32_t *dst, uint32_t offset, uint32_t num)
378 {
379     /* Suppress a compiler warning about unused variables */
380     (void) base;
381 
382     cy_en_efuse_status_t ret = CY_EFUSE_BAD_PARAM;
383 
384     if ((offset < EFUSE_SIZE) && ((EFUSE_SIZE - offset) >= (num * sizeof(uint32_t))))
385     {
386         for (; num != 0UL; --num)
387         {
388             *dst = CY_GET_REG32(CY_EFUSE_BASE + offset);
389             ++dst;
390             offset += 4UL; /* One 4-byte word is read at a time */
391         }
392         ret = CY_EFUSE_SUCCESS;
393     }
394     return ret;
395 }
396 
397 /**
398  *****************************************************************************
399  ** Cy_EFUSE_WriteBootRow
400  ** Writes data into BOsOTROW.
401  ** Before write operations you must call \ref Cy_EFUSE_Init().
402  ** It is recommended to disable the block when not using it.
403  ** Call \ref Cy_EFUSE_Disable() to disable the EFUSE block.
404  *****************************************************************************/
Cy_EFUSE_WriteBootRow(EFUSE_Type * base,uint32_t bootrow)405 cy_en_efuse_status_t Cy_EFUSE_WriteBootRow(EFUSE_Type *base, uint32_t bootrow)
406 {
407     /* Boot row is stored at address 0 of EFUSE macros 3-0 */
408     return Cy_EFUSE_WriteWord(base, bootrow, 0UL);
409 }
410 
411 /**
412  *****************************************************************************
413  ** Cy_EFUSE_ReadBootRow
414  ** Reads data from BOOTROW.
415  ** The BOOTROW information is latched upon system reset and is readable as
416  ** MMIO register.
417  *****************************************************************************/
Cy_EFUSE_ReadBootRow(EFUSE_Type * base,uint32_t * bootrow)418 cy_en_efuse_status_t Cy_EFUSE_ReadBootRow(EFUSE_Type *base, uint32_t *bootrow)
419 {
420     *bootrow = EFUSE_BOOTROW(base);
421     return CY_EFUSE_SUCCESS;
422 }
423 
424 
425 #endif /* #ifdef (CY_IP_MXEFUSE) && (CY_IP_MXEFUSE_VERSION >= 3) */
426 
427 /* [] END OF FILE */
428