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