blob: 08b99799f3ebdac91073328a3d40bc125fee48b2 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001// GEU_FuseWriteMethods.c
2//
3/******************************************************************************
4 *
5 * (C)Copyright 2005 - 2011 Marvell. All Rights Reserved.
6 *
7 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL.
8 * The copyright notice above does not evidence any actual or intended
9 * publication of such source code.
10 * This Module contains Proprietary Information of Marvell and should be
11 * treated as Confidential.
12 * The information in this file is provided for the exclusive use of the
13 * licensees of Marvell.
14 * Such users have the right to use, modify, and incorporate this code into
15 * products for purposes authorized by the license agreement provided they
16 * include this notice and the associated copyright notice with any such
17 * product.
18 * The information in this file is provided "AS IS" without warranty.
19
20 ******************************************************************************/
21#include <Typedef.h>
22#include <predefines.h>
23#include <geu_interface.h>
24#include <Errors.h>
25#include <timer.h>
26//#include <platform_timer.h>
27#include <PMUA.h>
28//#include <usbPal.h>
29#include <GEU.h>
30#include <platform_geu_fuse_internal.h>
31#include <USB_controller.h>
32#include <USB_PHY.h>
33#include <GEU_FuseReadMethods.h>
34
35// Comment out the following #define for debug to disable write protection checks
36// (Sticky bit set, lock bit set, or ECC programmed)in SetActiveFuseblock or SETUP... calls
37#define ENABLE_FUSEBLOCK_WRITE_PROTECT_CHECK 1 // Define for RELEASE
38//#define ENABLE_FUSEBLOCK_WRITE_PROTECT_CHECK 0 // Define for DEBUG
39
40//++
41//************************************************************
42// Unit Test Support
43// Reassigns GEU_REG_READ and GEU_REG_WRITE macros to emulator
44// function calls.
45#ifdef _GEU_EM
46#include "em_platform_geu_fuse_internal.h"
47#endif
48//************************************************************
49//--
50
51static struct GEU_FuseGlobalData g_ActiveFuseData = {0xF /*ActiveFuseBlock*/ };
52struct GEU_FuseGlobalData *pActiveFuseData = &g_ActiveFuseData;
53static struct GEU_FuseBurnStatus g_FuseBurnStatus;
54struct GEU_FuseBurnStatus *pFuseBurnStatus = &g_FuseBurnStatus;
55
56/***********************************************************
57* Function:
58* _geu_get_clock_divider
59*
60* Description:
61* Get the GEU clock divider by GEU HCLK.
62* GEU HCLK is the same as AXI ACLK
63* Input:
64* void
65* Output:
66* none
67* Returns:
68* clock divider
69************************************************************
70*/
71static UINT_T _geu_get_clock_divider(void)
72{
73 UINT_T geu_clk_divider = 0x7; /* set default value */
74 UINT_T axi_clock_selection;
75 UINT_T aclk_divider_selection;
76 UINT_T aclk_freq;
77
78 /* Get Clock Selection for ACLK */
79 GEU_REG_READ(PMUM_FCCR, axi_clock_selection); /* get AXI clock selection*/
80 axi_clock_selection = ((axi_clock_selection & PMUM_FCCR_ACLKSEL_BIT1)>>24) /* FCCR[25]: AXI clock selection bit[1] */
81 | ((axi_clock_selection & PMUM_FCCR_ACLKSEL_BIT0)>>19); /* FCCR[19]: AXI clock selection bit[0] */
82
83 switch(axi_clock_selection)
84 {
85 case 0x0:
86 axi_clock_selection = 416; /* this */
87 break;
88
89 case 0x1:
90 axi_clock_selection = 624;
91 break;
92
93 case 0x3:
94 axi_clock_selection = 312;
95 break;
96
97 default:
98 axi_clock_selection = 0;
99 break;
100 }
101
102 /* Get Clock Divider Selection for ACLK */
103 GEU_REG_READ(PMUA_CC_AP, aclk_divider_selection); /* 0xFD9219 for Nezha3 */
104 aclk_divider_selection = (aclk_divider_selection & PMUA_CC_AP_BUS_CLK_DIV_MSK) >> PMUA_CC_AP_BUS_CLK_DIV_BASE;
105 aclk_freq = axi_clock_selection / (aclk_divider_selection + 1);
106
107 /* GEU HCLK is the same clock source as ACLK, so it should be 208, 156, 104 or 74.
108 Some case if ACLK is not in this range, it's consider a abnormal clock.
109 On this abnormal case either we set GEU_CONFIG[27:25]=7 and set FUSE_SCLK_DIV_CNTR = HCLK/SCLK,
110 or return a error status because something wrong with the clock setting. */
111 switch(aclk_freq)
112 {
113 case 208:
114 geu_clk_divider = 0x2; /* 1 is also a coorect value */
115 break;
116
117 case 156:
118 geu_clk_divider = 0x3;
119 break;
120
121 case 104:
122 geu_clk_divider = 0x4; /* this */
123 break;
124
125 case 74:
126 geu_clk_divider = 0x5; /* 6 is also a correct value */
127 break;
128
129 default:
130 geu_clk_divider = 0x7;
131 break;
132 }
133
134 return geu_clk_divider;
135}
136
137/***********************************************************
138* Function:
139* _geuClearFuseBurnStatus(struct GEU_FuseBurnStatus *ptrFBS)
140*
141* Description:
142* Clears(zeros)all fields in a FuseBurnStatus structure.
143* Input:
144* Pointer to a Fuse Burn Status Structure.
145* Output:
146* none
147* Returns:
148* void
149************************************************************
150*/
151void _geuClearFuseBurnStatus(struct GEU_FuseBurnStatus *ptrFBS)
152{
153 INT i;
154 INT * ptr;
155
156 ptr = (INT*) ptrFBS;
157 for (i=0; i<(sizeof(struct GEU_FuseBurnStatus)/4); i++)
158 {
159 ptr[i] = 0x0;
160 }
161 return;
162}
163
164/***********************************************************
165* Function:
166* _geuClearActiveFuseData
167*
168* Description:
169* Clears fields in the ActiveFuseData structure used during a fuse burn.
170* Input:
171* None.
172* Output:
173* none
174* Returns:
175* void
176************************************************************
177*/
178
179void _geuClearActiveFuseData()
180{
181 INT i;
182 //struct GEU_FuseGlobalData * ptr;
183 UINT_T * ptr;
184
185 // Clear the ActiveFuseData
186 ptr = (UINT_T *) &g_ActiveFuseData;
187 for (i=0; i<(sizeof(g_ActiveFuseData)/4); i++)
188 {*ptr = 0; ptr++;}
189 return;
190}
191
192/***********************************************************
193* Function:
194* _geuConfirmPowerEnabledForFuseBurning
195*
196* Description:
197* Confirms the USB PHY Bandgap is enabled for the Fuse Power Regulator.
198* This is shared with the USB.
199* Input:
200* None.
201* Output:
202* none
203* Returns:
204* 0 - if Bandgap is disabled
205* 1 - if Bandgap is enabled
206************************************************************
207*/
208
209UINT_T _geuConfirmPowerEnabledForFuseBurning()
210{
211 return 1;
212}
213
214
215UINT_T GEU_EnableFuseBurnPower() //Changed from GEU_EnableUsbPhyBandgap
216{
217 //UINT_T result = NoError;
218 UINT_T scratch, clock_divider;
219 static UINT_T check=0;
220
221 if (check == 0) {
222
223 // According to Wei Ma turn wtm clk enable: REG32(0xd4282868) = 0xff; // wtm clk enable
224 GEU_REG_READ(PMUA_AES_CLK_RES_CTRL, scratch);
225 scratch |= (0xff);
226 GEU_REG_WRITE(PMUA_AES_CLK_RES_CTRL, scratch);
227
228 clock_divider = _geu_get_clock_divider();
229 GEU_REG_READ(GEU_CONFIG, scratch);
230 scratch &= (~GEU_CONFIG_FUSE_CLOCK_DIVIDER_MSK);
231 scratch = scratch | ((clock_divider) << GEU_CONFIG_FUSE_CLOCK_DIVIDER_BASE);
232 GEU_REG_WRITE(GEU_CONFIG, scratch);
233
234 GEU_REG_READ(PMUA_AES_CLK_RES_CTRL, scratch);
235 scratch |= PMUA_AES_CLK_RES_CTRL_AES_AXICLK_EN; //JML look into this, do we need to update it? It was WTMCLK
236 scratch |= PMUA_AES_CLK_RES_CTRL_AES_AXI_RST;
237 GEU_REG_WRITE(PMUA_AES_CLK_RES_CTRL, scratch);
238 Delay(1000);
239
240 GEU_REG_READ(REGULATOR_CNT_REG, scratch);
241 scratch |= 0x00f00205; //JML - sample code from Wei Ma, need to check this
242 GEU_REG_WRITE(REGULATOR_CNT_REG, scratch);
243 Delay(1000);
244
245
246 GEU_REG_READ(FUSE_SCLK_DIV_CNTR, scratch);
247 scratch = 0xe0; //0x340; //JML - sample code from Wei Ma, need to check this
248 GEU_REG_WRITE(FUSE_SCLK_DIV_CNTR, scratch);
249 Delay(1000);
250 }
251 check++;
252 return NoError;
253}
254
255UINT_T GEU_DisablePowerForFuseBurning()
256{
257
258 return NoError;
259}
260
261
262/***********************************************************
263* Function:
264* _geuUpdateUserFuseBurnStatus
265*
266* Description:
267* Copies the internal GEU_FuseBurnStatus structure to the user specified buffer.
268* Returns the status passed in as this is generally called to return from a fuse burn
269* function
270* Input:
271* pUserFuseBurnStatus - Pointer to a buffer large enough to contain the FuseBurnStatus structure.
272* status - status to return
273* Output:
274* none
275* Returns:
276* status passed by the calling routine
277************************************************************
278*/
279UINT_T _geuUpdateUserFuseBurnStatus(struct GEU_FuseBurnStatus *pUserFuseBurnStatus, UINT_T status)
280{
281 UINT_T i;
282 UINT_T * dptr, * sptr;
283 pFuseBurnStatus->FinalBurnStatus = status ;
284 // copy Fuse Burn Status to Users Fuse Burn Status
285 dptr = (UINT_T *) pUserFuseBurnStatus;
286 sptr = (UINT_T *) pFuseBurnStatus;
287 for (i=0; i<(sizeof(struct GEU_FuseBurnStatus)/4); i++)
288 {
289 *dptr = *sptr;
290 dptr++;
291 sptr++;
292 }
293 return (status);
294}//End Routine _geuUpdateUserFuseBurnStatus
295
296/***********************************************************
297* Function:
298* _getCopyOfActiveFuseData
299*
300* Description:
301* Copies the internal GEU_FuseGlobalData structure to the specified buffer.
302*
303* Input:
304* pUserFuseData - Pointer to a buffer large enough to contain the FuseGlobalData structure.
305*
306* Output:
307* none
308* Returns:
309* NoError
310* WriteError - pUserFuseData = 0
311*
312************************************************************/
313//UINT_T _getCopyOfActiveFuseData(struct GEU_FuseGlobalData *pUserFuseData);
314//UINT_T _getCopyOfActiveFuseData(struct GEU_FuseGlobalData *pUserFuseData)
315UINT _getCopyOfActiveFuseData(struct GEU_FuseGlobalData *pUserFuseData)
316{
317 UINT_T i, return_status;
318 UINT_T * dptr, * sptr;
319
320 if (pUserFuseData == 0)
321 {return_status = WriteError;}
322 else
323 {
324 // copy Fuse Data to User Area
325 dptr = (UINT_T *) pUserFuseData; //Destination Pointer
326 sptr = (UINT_T *) pActiveFuseData; //Source Pointer
327 for (i=0; i<(sizeof(g_ActiveFuseData)/4); i++)
328 {
329 *dptr = *sptr;
330 dptr++;
331 sptr++;
332 }
333 return_status = NoError;
334 }
335 return (return_status);
336}
337
338/***********************************************************
339* Function:
340* _geuClearVal1Val2RegisterSets()
341*
342* Description:
343* Clears the GEU_FUSE_PROG_VAL1 and GEU_FUSE_PROG_VAL2 register sets.
344*
345* Input:
346* none
347*
348* Output:
349* none
350* Returns:
351* void
352*
353*
354************************************************************/
355void _geuClearVal1Val2RegisterSets()
356{
357 // Clear VAL1 & VAL2 register sets
358 GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+0, 0);
359 GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+4, 0);
360 GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+8, 0);
361 GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+12, 0);
362 GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+0, 0);
363 GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+4, 0);
364 GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+8, 0);
365 GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+12, 0);
366 return;
367}
368
369/***********************************************************
370* Function:
371* _geuFuseSoftwareReset
372*
373* Description:
374* Implements a Fuse Software Reset
375*
376* Input:
377* none
378*
379* Output:
380* none
381* Returns:
382* void
383*
384*
385************************************************************/
386UINT_T _geuFuseSoftwareReset()
387{
388 UINT_T scratch, return_status, status;
389
390 return_status = 0;
391
392 // Toggle Fuse Software Reset
393 // - Must be done to enable fuse block reads
394
395 // Clear the Fuse Software Reset Bit (It should alread by zero)
396 GEU_REG_READ(GEU_CONFIG, scratch);
397 scratch = scratch & ~GEU_CONFIG_FUSE_SOFTWARE_RESET;
398 GEU_REG_WRITE(GEU_CONFIG, scratch);
399 Delay(5);
400
401 // Set the Fuse Software Reset Bit
402 GEU_REG_READ(GEU_CONFIG, scratch);
403 scratch = scratch | GEU_CONFIG_FUSE_SOFTWARE_RESET;
404 GEU_REG_WRITE(GEU_CONFIG, scratch);
405 Delay(5);
406
407 // Clear the Fuse Software Reset Bit
408 GEU_REG_READ(GEU_CONFIG, scratch);
409 scratch = scratch & ~GEU_CONFIG_FUSE_SOFTWARE_RESET;
410 GEU_REG_WRITE(GEU_CONFIG, scratch);
411
412
413 // Wait for FUSE_READY
414 status = _geuWaitForFuseOperationComplete(GEU_FUSE_STATUS_FUSE_READY, 10);
415 if (status !=0)
416 {
417 return_status |= K_FUSE_READY_TIMEOUT;
418 }
419 return return_status;
420}
421
422UINT_T _geuReadFuseBlockLockStatus(UINT_T fuseblock)
423{
424 UINT_T scratch = 0;
425
426 GEU_REG_READ(GEU_FUSE_STATUS, scratch);
427
428 switch(fuseblock)
429 {
430 case(0):
431 {
432 scratch &= GEU_FUSEBLOCK_0_LOCK_BIT_MASK;
433 break;
434 }
435 case(1):
436 {
437 scratch &= GEU_FUSEBLOCK_1_LOCK_BIT_MASK;
438 break;
439 }
440 case(2):
441 {
442 scratch &= GEU_FUSEBLOCK_2_LOCK_BIT_MASK;
443 break;
444 }
445 case(3):
446 {
447 scratch &= GEU_FUSEBLOCK_3_LOCK_BIT_MASK;
448 break;
449 }
450 case(4):
451 {
452 scratch &= GEU_FUSEBLOCK_4_LOCK_BIT_MASK;
453 break;
454 }
455 case(5):
456 {
457 scratch &= GEU_FUSEBLOCK_5_LOCK_BIT_MASK;
458 break;
459 }
460 case(6):
461 {
462 scratch &= GEU_FUSEBLOCK_6_LOCK_BIT_MASK;
463 break;
464 }
465 case(7):
466 {
467 scratch &= GEU_FUSEBLOCK_7_LOCK_BIT_MASK;
468 break;
469 }
470 case(8):
471 {
472 scratch &= GEU_FUSEBLOCK_8_LOCK_BIT_MASK;
473 break;
474 }
475 case(9):
476 {
477 scratch &= GEU_FUSEBLOCK_9_LOCK_BIT_MASK;
478 break;
479 }
480 case(10):
481 {
482 scratch &= GEU_FUSEBLOCK_10_LOCK_BIT_MASK;
483 break;
484 }
485 case(11):
486 {
487 scratch &= GEU_FUSEBLOCK_11_LOCK_BIT_MASK;
488 break;
489 }
490 default:
491 {break;}
492 }//EndSwitch
493 if (scratch)
494 {
495 return 1;
496 }
497 else
498 {
499 return 0;
500 }
501}//EndRoutine _geuReadFuseBlockLockStatus
502
503/***********************************************************
504* Function:
505* _geuFuseBurn
506*
507* Description:
508* Implements a Fuse Burn.
509* Upon completeion of the burn:
510* - Does a Fuse Software Reset (enables reading fuse registers)
511* - Saves the GEU_ECC_CAL register (ECC value) to the GlobalFuseData structure
512*
513* Input:
514* n - Fuse Block Number
515* Lock - Burns the Lock bit for the fuse block
516*
517* Output:
518* Always saves the EU_ECC_CAL value in the ActiveFuseData structure even thought
519* it may not apply to the particular fuse block field being burned.
520* Returns:
521* void
522*
523*
524************************************************************/
525UINT_T _geuBurnFuse(UINT_T n, UINT_T Lock)
526{
527 UINT_T scratch, config_save, status, return_status, geu_clk_divider;
528
529 return_status = 0;
530
531 status = _geuFuseSoftwareReset();
532 if (status != 0) {
533 return_status |= status;
534 }
535
536 //Save the current GEU_CONFIG state
537 GEU_REG_READ(GEU_CONFIG, config_save);
538
539 // Enable High Voltage
540 GEU_REG_READ(GEU_CONFIG, scratch);
541 scratch = scratch | GEU_CONFIG_HIGH_VOLT_ENABLE;
542 GEU_REG_WRITE(GEU_CONFIG, scratch);
543
544 // Wait 1 msec for High Voltage to stabilize
545 Delay(K_FuseHighVoltEnableDelay);
546
547 // refer from ULC1, 20150211 set geu clock divider value
548 // 0x3 - aclk@156Mhz, 0x4 - aclk@104Mhz
549 geu_clk_divider = _geu_get_clock_divider();
550 // consider 0b111 is a wrong setting
551 if (geu_clk_divider == (GEU_CONFIG_FUSE_CLOCK_DIVIDER_MSK >> GEU_CONFIG_FUSE_CLOCK_DIVIDER_BASE) )
552 {
553 return K_FUSE_WRONG_ACLK_SETTING;
554 }
555 scratch = scratch & (~GEU_CONFIG_FUSE_CLOCK_DIVIDER_MSK);
556 scratch = scratch | ((geu_clk_divider) << GEU_CONFIG_FUSE_CLOCK_DIVIDER_BASE);
557
558 //Build a burn command
559 // Set the clock divider to zero [27:25]
560 //scratch = scratch & (~GEU_CONFIG_FUSE_CLOCK_DIVIDER_MSK);
561 // Clear Fuse Block Number field [20:18]
562 scratch = scratch & (~GEU_CONFIG_FUSE_BLOCK_NUMBER_MSK);
563 // Set Fuse Block number[20:18]
564 scratch = scratch |((n & 0x7)<< GEU_CONFIG_FUSE_BLOCK_NUMBER_BASE);
565 // Set BURN_FUSE_ENABLE[16] and ENABLE_SOFT_FUSE_PROG[14]
566 scratch = scratch |(GEU_CONFIG_BURN_FUSE_ENABLE | GEU_CONFIG_ENABLE_SOFT_FUSE_PROG);
567
568 // Set FuseLock if requested
569 if (Lock) {
570 scratch = scratch | (GEU_CONFIG_FUSE_LOCK);
571 }
572 // BURN FUSE - Update GEU_CONFIG with burn parameters
573 GEU_REG_WRITE(GEU_CONFIG, scratch);
574
575
576 // Wait for Burn Complete status
577 status = _geuWaitForFuseOperationComplete(GEU_FUSE_STATUS_FUSE_BURN_DONE, 10);
578 if (status != 0) {
579 return_status |= K_FUSE_BURN_TIMEOUT;
580 }
581
582 scratch = config_save; //| GEU_CONFIG_BURN_FUSE_ENABLE;
583 GEU_REG_WRITE(GEU_CONFIG, scratch);
584
585 status = _geuFuseSoftwareReset();
586 if (status != 0) {
587 return_status |= status;
588 }
589
590 GEU_REG_WRITE(GEU_CONFIG, config_save);
591
592 // Save the ECC CAL value
593 GEU_REG_READ(GEU_ECC_CAL, pActiveFuseData->EccCalRegSave);
594 return return_status;
595}
596
597
598
599/***********************************************************
600* Function:
601* GEU_SetActiveFuseBlock
602*
603* Description:
604* Sets the active fuse block for a set of operations.
605* This restricts operations to the specifed fuseblock.
606* Operations not targeted to the active fuseblock will fail.
607* Notes:
608* 1. The specified fuseblock must not be locked.
609* 2. The sticky bit must not be set.
610* 3. The GlobalFuseData structure (*pActveFuseBlock) is initialized.
611* 4. The FuseBurnStatus structure (*pFuseBurnStatus) is initialized.
612* 5. The SQU0, SQU1, and SQU2 fuseblocks are not supported.
613* 6. Fuseblock numbers below are also supported
614* K_NO_FUSEBLOCK
615* K_UNDEFINED_FUSEBLOCK
616* to allow clearing the internal data structures without specifying
617* a legitimate fuseblock.
618* 7. The ActiveFuseBlockField is initialize to K_UNDEFINED_FUSEBLOCK_FIELD
619*
620* Input:
621* n - Fuse Block Number
622* K_AP_CONFIG_FUSEBLOCK
623* K_CP_CONFIG_FUSEBLOCK
624* K_USBID_FUSEBLOCK
625* K_APCPUSB_FUSEBLOCK
626* K_LIFECYCLE_FUSEBLOCK
627* K_SOFTWARE_VERSION_FUSEBLOCK
628* K_RKEK_FUSEBLOCK
629* K_OEM_FUSEBLOCK
630* K_JTAG_FUSEBLOCK
631* K_ECC_FUSEBLOCK
632* K_NO_FUSEBLOCK
633* K_UNDEFINED_FUSEBLOCK
634* Output:
635* none
636* Returns:
637* NoError
638* FUSE_FuseBlockLocked
639* FUSE_UnsupportedFuseBlock
640*
641*
642************************************************************/
643UINT_T GEU_SetActiveFuseBlock(UINT_T n)
644{
645 UINT_T scratch;
646
647 if (pActiveFuseData->ActiveFuseBlock != n)
648 {
649 // check if fuseblock locked (sticky or permanent)
650 switch (n)
651 {
652#if 0
653 case(K_AP_CONFIG_FUSEBLOCK):
654 // K_CP_CONFIG_FUSEBLOCK
655 // K_USBID_FUSEBLOCK
656 // K_APCPUSB_FUSEBLOCK
657 // K_LIFECYCLE_FUSEBLOCK
658 // K_SOFTWARE_VERSION_FUSEBLOCK
659 // K_ECC_FUSEBLOCK
660 {
661 // Check Sticky Bit
662 GEU_REG_READ(GEU_CONFIG, scratch);
663 if ((scratch & GEU_CONFIG_STICKY_CONTROL_BIT) != 0)
664 {
665 return(FUSE_FuseBlockStickyBitSet);
666 }
667 // Check Lock Bit
668#if ENABLE_FUSEBLOCK_WRITE_PROTECT_CHECK
669 GEU_REG_READ(GEU_FUSE_STATUS, scratch);
670 scratch = (scratch & GEU_FUSE_STATUS_LOCK_BIT_MSK)>>GEU_FUSE_STATUS_LOCK_BIT_BASE;
671 if (scratch & K_FB0_FUSE_LOCK_BIT_MASK)
672 {
673 return(FUSE_FuseBlockLocked);
674 }
675#endif
676 break;
677 }
678 case(K_RKEK_FUSEBLOCK):
679 {
680 // Check Lock Bit
681#if ENABLE_FUSEBLOCK_WRITE_PROTECT_CHECK
682 GEU_REG_READ(GEU_FUSE_STATUS, scratch);
683 scratch = (scratch & GEU_FUSE_STATUS_LOCK_BIT_MSK)>>GEU_FUSE_STATUS_LOCK_BIT_BASE;
684 if (scratch & K_RKEK_FUSE_LOCK_BIT_MASK)
685 {
686 return(FUSE_FuseBlockLocked);
687 }
688#endif
689 break;
690 }
691 case(K_SQU0_FUSE_LOCK_BIT_MASK):
692 case(K_SQU1_FUSE_LOCK_BIT_MASK):
693 case(K_SQU2_FUSE_LOCK_BIT_MASK):
694 {
695 return(FUSE_UnsupportedFuseBlock);
696 //break; //JML - Compiled complained statement unreachable
697 }
698
699 case(K_OEM_FUSEBLOCK):
700 {
701 // Check Lock Bit
702#if ENABLE_FUSEBLOCK_WRITE_PROTECT_CHECK
703 GEU_REG_READ(GEU_FUSE_STATUS, scratch);
704 scratch = (scratch & GEU_FUSE_STATUS_LOCK_BIT_MSK)>>GEU_FUSE_STATUS_LOCK_BIT_BASE;
705 if (scratch & K_OEM_FUSE_LOCK_BIT_MASK)
706 {
707 return(FUSE_FuseBlockLocked);
708 }
709#endif
710 break;
711 }
712 #endif
713 case(K_JTAG_FUSEBLOCK):
714 {
715 // Check Lock Bit
716#if ENABLE_FUSEBLOCK_WRITE_PROTECT_CHECK
717 GEU_REG_READ(GEU_FUSE_STATUS, scratch);
718 scratch = (scratch & GEU_FUSE_STATUS_LOCK_BIT_MSK)>>GEU_FUSE_STATUS_LOCK_BIT_BASE;
719 if (scratch & K_JTAG_FUSE_LOCK_BIT_MASK)
720 {
721 return(FUSE_FuseBlockLocked);
722 }
723#endif
724 break;
725 }
726 case(K_FB7_FUSEBLOCK):
727 {
728 // Check Lock Bit
729#if ENABLE_FUSEBLOCK_WRITE_PROTECT_CHECK
730 GEU_REG_READ(GEU_FUSE_STATUS, scratch);
731 scratch = (scratch & GEU_FUSE_STATUS_LOCK_BIT_MSK)>>GEU_FUSE_STATUS_LOCK_BIT_BASE;
732 if (scratch & K_FB7_FUSE_LOCK_BIT_MASK)
733 {
734 return(FUSE_FuseBlockLocked);
735 }
736#endif
737 break;
738 }
739 default:
740 // Invalid or NO_FUSEBLOCK(as opposed to UNSUPPORTED)is OK
741 break;
742 }
743 // Clear the Fuse Burn Status Block
744 _geuClearFuseBurnStatus(pFuseBurnStatus);
745
746 // Clear the ActiveFuseData
747 _geuClearActiveFuseData();
748
749 // Clear VAL1 & VAL2 register sets
750 _geuClearVal1Val2RegisterSets();
751
752 pActiveFuseData->ActiveFuseBlock = n;
753 pActiveFuseData->ActiveFuseBlockField = K_UNDEFINED_FUSEBLOCK_FIELD;
754 pActiveFuseData->FuseLockBitMask = 0x01 << n;
755 }//EndIf BlockNotActive
756 return 0;
757}//End Routine SetActiveFuseBlock
758
759/***********************************************************
760* Function:
761* GEU_ReadActiveFuseBlockNumber
762*
763* Description:
764* Returns the Active Fuse Block number
765
766* Input:
767* none
768*
769* Output:
770* none
771* Returns:
772* Active Fuse Block Number
773*
774*
775************************************************************/
776UINT_T GEU_ReadActiveFuseBlockNumber()
777{
778return (pActiveFuseData->ActiveFuseBlock);
779}
780
781
782/***********************************************************
783* Function:
784* GEU_SetupSecurityConfigFuseBits
785*
786* Description:
787* - Confirms the Active FuseBlock and FuseBlockField conform to the
788* Security Usb fuseblock field.
789* - Copies the caller supplied Security Config data(32 bits/4 bytes) to
790* the appropriate offset in the GEU_FUSE_PROG_VALn register set.
791* - Sets the CpC Burn Request.
792*
793* Input:
794* pBuffer - pointer to a buffer containing the 32 bits of USB ID data
795* Size - Size (in bytes) of the data to copy (Must be K_USBID_FUSE_SIZE).
796*
797* Output:
798* none
799* Returns:
800* NoError
801* FUSE_FuseBlockNotActive
802* FUSE_FuseBlockFieldNotActive
803* FUSE_BufferTooSmall
804*
805************************************************************/
806UINT_T GEU_SetupSecurityConfigFuseBits(UINT_T* pBuffer, UINT_T Size)
807{
808 UINT_T scratch;
809
810 if (Size != K_SECURITY_CONFIG_FUSE_SIZE)
811 {
812 return FUSE_BufferTooSmall;
813 }
814
815 // Confirm this fuseblock is active
816 if (g_ActiveFuseData.ActiveFuseBlock != K_SECURITYCONFIG_FUSEBLOCK)
817 {
818 return (FUSE_FuseBlockNotActive);
819 }
820
821 // Check Active FuseBlock Field
822 //If not set, set it to ApCpUsb
823 if (pActiveFuseData->ActiveFuseBlockField == K_UNDEFINED_FUSEBLOCK_FIELD)
824 {
825 //Set ActiveFuseBlockField - this is first one
826 pActiveFuseData->ActiveFuseBlockField = K_SECURITY_USBID_FUSEBLOCK_FIELD;
827 }
828 else
829 {
830 // If the Active FuseBlock Field is NOT Security USB return error
831 if (pActiveFuseData->ActiveFuseBlockField != K_SECURITY_USBID_FUSEBLOCK_FIELD)
832 {
833 return (FUSE_FuseBlockFieldNotActive);
834 }
835 }
836
837#if ENABLE_FUSEBLOCK_WRITE_PROTECT_CHECK
838 // Sticky bit only for block 0. Remove
839 GEU_REG_READ(GEU_CONFIG, scratch);
840 // if ((scratch & GEU_CONFIG_STICKY_CONTROL_BIT) != 0)
841 // {
842 // return(FUSE_FuseBlockStickyBitSet);
843 // }
844 // Check Lock Bit
845 GEU_REG_READ(GEU_FUSE_STATUS, scratch);
846 scratch = (scratch & GEU_FUSE_STATUS_LOCK_BIT_MSK)>>GEU_FUSE_STATUS_LOCK_BIT_BASE;
847 if (scratch & K_FB7_FUSE_LOCK_BIT_MASK)
848 {
849 return(FUSE_FuseBlockLocked);
850 }
851 // Check if ECC protected
852 GEU_REG_READ(GEU_FUSE_VAL_SECURITY_USB_ECC, scratch);
853 if ((scratch & GEU_SECURITY_USB_ECC_MASK) != 0)
854 {
855 return(FUSE_FieldWriteProtectedByEcc);
856 }
857#endif
858
859 // Clear Burn Data in the Active Fuse Data Structure
860 // JLC: _geuClearActiveFuseData();
861
862 //Save the setup data to GEU_FUSE_PROG_VAL1/VAL2
863 // Bytes 3-0
864 scratch = pBuffer[0];
865 _geuUpdateRegister(GEU_FUSE_PROG_VAL1+0, scratch, 0xFFFFFFFF);
866
867 // Save to Active fuseblock for burn validation later
868 pActiveFuseData->SecurityConfigSave[0] = scratch;
869
870 //Set Burn Request
871 pActiveFuseData->BurnRequest |= K_SECURITY_CONFIG_BURN_REQUEST_MASK;
872
873 return 0;
874}
875
876
877/**********************************************************
878* Function:
879* GEU_SetupOemHashKeyFuseBits
880*
881* Description:
882* - Confirms the Active FuseBlock and FuseBlockField conform to the
883* OEM Hash fuseblock field.
884* - Copies the caller supplied OEM Hash data(32 bytes) to
885* the appropriate offset in the GEU_FUSE_PROG_VALn register set.
886* - Sets the OEM Burn Request.
887*
888* Input:
889* pBuffer - pointer to a buffer containing the 32 bytes of OEM Hash data
890* Size - Size (in bytes) of the data to copy (Must be K_OEM_HASH_FUSE_SIZE).
891*
892* Output:
893* none
894* Returns:
895* NoError
896* FUSE_FuseBlockNotActive
897* FUSE_FuseBlockFieldNotActive
898* FUSE_InvalidBufferSize
899*
900************************************************************/
901UINT_T GEU_SetupOemHashKeyFuseBits(UINT_T* pBuffer, UINT_T Size)
902{
903 UINT_T scratch;
904
905 if (Size != K_OEM_HASH_FUSE_SIZE)
906 {
907 return FUSE_InvalidBufferSize;
908 }
909 // Confirm this fuseblock is active
910 if (g_ActiveFuseData.ActiveFuseBlock != K_OEM_FUSEBLOCK)
911 {
912 return (FUSE_FuseBlockNotActive);
913 }
914
915 // Check Active FuseBlock Field
916 //If not set, set it.
917 if (pActiveFuseData->ActiveFuseBlockField == K_UNDEFINED_FUSEBLOCK_FIELD)
918 {
919 //Set ActiveFuseBlockField - this is first one
920 pActiveFuseData->ActiveFuseBlockField = K_OEM0_FUSEBLOCK_FIELD;
921 }
922 else
923 {
924 // If the Active FuseBlock Field is NOT OEM HASH KEY return error
925 if (pActiveFuseData->ActiveFuseBlockField != K_OEM0_FUSEBLOCK_FIELD)
926 {
927 return (FUSE_FuseBlockFieldNotActive);
928 }
929 }
930
931#if ENABLE_FUSEBLOCK_WRITE_PROTECT_CHECK
932 // Check Lock Bit
933 GEU_REG_READ(GEU_FUSE_STATUS, scratch);
934 scratch = (scratch & GEU_FUSE_STATUS_LOCK_BIT_MSK)>>GEU_FUSE_STATUS_LOCK_BIT_BASE;
935 if (scratch & K_OEM_FUSE_LOCK_BIT_MASK)
936 {
937 return(FUSE_FuseBlockLocked);
938 }
939 // Check ECC programmed
940 GEU_REG_READ(GEU_FUSE_VAL_OEM_KEY0_HASH_ECC, scratch);
941 if (scratch != 0)
942 {
943 return(FUSE_FieldWriteProtectedByEcc);
944 }
945#endif
946
947 // Clear Burn Data in the Active Fuse Data Structure
948 // JLC: _geuClearActiveFuseData();
949
950 // Save to Active fuseblock for burn validation later
951 pActiveFuseData->FuseBlockSave[0] = pBuffer[0];
952 pActiveFuseData->FuseBlockSave[1] = pBuffer[1];
953 pActiveFuseData->FuseBlockSave[2] = pBuffer[2];
954 pActiveFuseData->FuseBlockSave[3] = pBuffer[3];
955 pActiveFuseData->FuseBlockSave[4] = pBuffer[4];
956 pActiveFuseData->FuseBlockSave[5] = pBuffer[5];
957 pActiveFuseData->FuseBlockSave[6] = pBuffer[6];
958 pActiveFuseData->FuseBlockSave[7] = pBuffer[7];
959
960 //Save the setup data to GEU_FUSE_PROG_VAL1/VAL2
961
962 GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+0, pBuffer[0]);
963 GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+4, pBuffer[1]);
964 GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+8, pBuffer[2]);
965 GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+12, pBuffer[3]);
966 GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+0, pBuffer[4]);
967 GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+4, pBuffer[5]);
968 GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+8, pBuffer[6]);
969 GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+12, pBuffer[7]);
970
971 //Set Burn Request
972 pActiveFuseData->BurnRequest |= K_OEM_KEY0_BURN_REQUEST_MASK;
973
974 return 0;
975}//End Routine GEU_SetupOemHashFuseBits
976
977
978/**********************************************************
979* Function:
980* GEU_SetupOemJtagHashKeyFuseBits
981*
982* Description:
983* - Confirms the Active FuseBlock and FuseBlockField conform to the
984* JTAG fuseblock field.
985* - Copies the caller supplied JTAG Hash data(32 bytes) to
986* the appropriate offset in the GEU_FUSE_PROG_VALn register set.
987* - Sets the JTAG Burn Request.
988*
989* Input:
990* pBuffer - pointer to a buffer containing the 32 bytes of JTAG Hash data
991* Size - Size (in bytes) of the data to copy (Must be K_JTAG_FUSE_SIZE).
992*
993* Output:
994* none
995* Returns:
996* NoError
997* FUSE_FuseBlockNotActive
998* FUSE_FuseBlockFieldNotActive
999* FUSE_InvalidBufferSize
1000*
1001************************************************************/
1002UINT_T GEU_SetupOemJtagHashKeyFuseBits(UINT_T* pBuffer, UINT_T Size)
1003{
1004 UINT_T scratch;
1005
1006 if (Size != K_JTAG_HASH_FUSE_SIZE)
1007 {
1008 return FUSE_InvalidBufferSize;
1009 }
1010
1011 // Confirm this fuseblock is active
1012 if (g_ActiveFuseData.ActiveFuseBlock != K_JTAG_FUSEBLOCK)
1013 {
1014 return (FUSE_FuseBlockNotActive);
1015 }
1016
1017 // Check Active FuseBlock Field
1018 //If not set, set it.
1019 if (pActiveFuseData->ActiveFuseBlockField == K_UNDEFINED_FUSEBLOCK_FIELD)
1020 {
1021 //Set ActiveFuseBlockField - this is first one
1022 pActiveFuseData->ActiveFuseBlockField = K_JTAG0_FUSEBLOCK_FIELD;
1023 }
1024 else
1025 {
1026 // If the Active FuseBlock Field is NOT JTAG Hash Key, return error
1027 if (pActiveFuseData->ActiveFuseBlockField != K_JTAG0_FUSEBLOCK_FIELD)
1028 {
1029 return (FUSE_FuseBlockFieldNotActive);
1030 }
1031 }
1032
1033#if ENABLE_FUSEBLOCK_WRITE_PROTECT_CHECK
1034 // Check Lock Bit
1035 GEU_REG_READ(GEU_FUSE_STATUS, scratch);
1036 scratch = (scratch & GEU_FUSE_STATUS_LOCK_BIT_MSK)>>GEU_FUSE_STATUS_LOCK_BIT_BASE;
1037 if (scratch & K_JTAG_FUSE_LOCK_BIT_MASK)
1038 {
1039 return(FUSE_FuseBlockLocked);
1040 }
1041 // Check if ECC programmed
1042 GEU_REG_READ(GEU_FUSE_VAL_OEM_JTAG_KEY_HASH_ECC, scratch);
1043 if (scratch != 0)
1044 {
1045 return(FUSE_FieldWriteProtectedByEcc);
1046 }
1047#endif
1048
1049 // Clear Burn Data in the Active Fuse Data Structure
1050 // JLC: _geuClearActiveFuseData();
1051
1052 // Save to Active fuseblock for burn validation later
1053 pActiveFuseData->FuseBlockSave[0] = pBuffer[0];
1054 pActiveFuseData->FuseBlockSave[1] = pBuffer[1];
1055 pActiveFuseData->FuseBlockSave[2] = pBuffer[2];
1056 pActiveFuseData->FuseBlockSave[3] = pBuffer[3];
1057 pActiveFuseData->FuseBlockSave[4] = pBuffer[4];
1058 pActiveFuseData->FuseBlockSave[5] = pBuffer[5];
1059 pActiveFuseData->FuseBlockSave[6] = pBuffer[6];
1060 pActiveFuseData->FuseBlockSave[7] = pBuffer[7];
1061
1062 //Save the setup data to GEU_FUSE_PROG_VAL1/VAL2
1063
1064 GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+0, pBuffer[0]);
1065 GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+4, pBuffer[1]);
1066 GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+8, pBuffer[2]);
1067 GEU_REG_WRITE(GEU_FUSE_PROG_VAL1+12, pBuffer[3]);
1068 GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+0, pBuffer[4]);
1069 GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+4, pBuffer[5]);
1070 GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+8, pBuffer[6]);
1071 GEU_REG_WRITE(GEU_FUSE_PROG_VAL2+12, pBuffer[7]);
1072
1073 //Set Burn Request
1074 pActiveFuseData->BurnRequest |= K_JTAG_KEY0_BURN_REQUEST_MASK;
1075
1076 return 0;
1077}
1078
1079
1080
1081/**********************************************************
1082* Function:
1083* GEU_BurnFuseBlock_OemHashKey
1084*
1085* Description:
1086* Burns the OEM Hash Key field in the OEM Hash Key Fuseblock.
1087*
1088* - Confirms that a OEM Hash Key burn request exists
1089* - Burns the fuseblock
1090* Validates the burned OEM Hash Key equals the requested OEM Hash key
1091* Retries if compare fails
1092*
1093* Input:
1094* pUserFuseBurnStatus - pointer to a buffer containing a FuseBurnStatus structure
1095*
1096* Output:
1097* none
1098* Returns:
1099* NoError
1100* FUSE_BurnError
1101*
1102************************************************************/
1103UINT_T GEU_BurnFuseBlock_OemHashKey(struct GEU_FuseBurnStatus * pUserFuseBurnStatus)
1104{
1105 UINT_T temp[8]; // temp buffer for fuse block compares
1106 UINT_T status;
1107
1108 // Confirm this fuseblock is active
1109 if (pActiveFuseData->ActiveFuseBlock != K_OEM_FUSEBLOCK)
1110 {
1111 return (FUSE_FuseBlockNotActive);
1112 }
1113 // Confirm bandgap from USB PHY is enabled for the fuse power regulator
1114 if( _geuConfirmPowerEnabledForFuseBurning() == 0)
1115 {
1116 pFuseBurnStatus->FinalBurnStatus = FUSE_FuseBurnPowerNotEnabled;
1117 return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus->FinalBurnStatus));
1118 }
1119
1120 // Save the burn request in the FuseBurnStatus
1121 pFuseBurnStatus->SavedBurnRequest = pActiveFuseData->BurnRequest;
1122
1123 if ((pActiveFuseData->BurnRequest & K_OEM_KEY0_BURN_REQUEST_MASK) == 0)
1124 {
1125 return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, FUSE_NoBurnRequest));
1126 }
1127
1128 // Burn Count = 0
1129 pActiveFuseData->BurnCount = 0;
1130
1131 while (pActiveFuseData->BurnRequest)
1132 {
1133 //++ ****** Burn **********
1134 status = _geuBurnFuse(K_OEM_FUSEBLOCK, K_DO_NOT_LOCK_FUSEBLOCK); // Burn and NOT Lock OEM Key Hash
1135 //-- ****** Burn **********
1136 if (status != 0)
1137 {
1138 pFuseBurnStatus->DebugStatus = status;
1139 }
1140
1141 // Burn Count++
1142 pActiveFuseData->BurnCount++;
1143 if (pActiveFuseData->BurnCount > 1)
1144 {
1145 pFuseBurnStatus->DebugStatus |= K_MULTIPLE_BURN_COUNT;
1146 }
1147
1148 //********************************************************************
1149 // Validate the OEM Hash Burn
1150 //********************************************************************
1151
1152 if ((pActiveFuseData->BurnRequest & K_OEM_KEY0_BURN_REQUEST_MASK) != 0)
1153 {
1154 //Compare Burned value with Saved value
1155 status = GEU_ReadOemHashKeyFuseBits(&temp[0], K_FUSEBLOCK_SIZE);
1156 status = _geu_compare(&pActiveFuseData->FuseBlockSave[0],
1157 &temp[0],
1158 K_FUSEBLOCK_SIZE);
1159 if (status == 0)
1160 {
1161 // AP Burn Good - Clear the Burn Request
1162 pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest
1163 & ~K_OEM_KEY0_BURN_REQUEST_MASK;
1164 }
1165 else
1166 {
1167 // If the BurnCount is 1, leave the burn request set
1168 // for another try.
1169 // Else
1170 if (pActiveFuseData->BurnCount >= 2)
1171 {
1172 // Burn Failed two times - Clear the burn Request
1173 pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest
1174 & ~K_OEM_KEY0_BURN_REQUEST_MASK;
1175 // Set the AP Raw Burn Status to indicate Failure
1176 pFuseBurnStatus->RawBurnStatus = pFuseBurnStatus->RawBurnStatus |
1177 K_OEM_KEY0_STATUS_BIT_MASK;
1178 }
1179 }//EndIfElse
1180 }//Endif
1181 }//End While
1182 // Set status
1183 pFuseBurnStatus->CorrectedBurnStatus = pFuseBurnStatus->RawBurnStatus;
1184 pFuseBurnStatus->FinalBurnStatus = NoError;
1185 if(pFuseBurnStatus->CorrectedBurnStatus != 0)
1186 {
1187 pFuseBurnStatus->FinalBurnStatus = FUSE_BurnError;
1188 }
1189
1190 return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus->FinalBurnStatus));
1191}// End Routine GEU_BurnFuseBlock_OEM_Platform_Hash
1192
1193/**********************************************************
1194* Function:
1195* GEU_BurnFuseBlock_OemJtagHashKey
1196*
1197* Description:
1198* Burns the OEM JTAG Hash Key field in the OEM JTAG Hash Key Fuseblock.
1199*
1200* - Confirms that a OEM JTAG Hash Key burn request exists
1201* - Burns the fuseblock
1202* Validates the burned OEM JTAG Hash Key equals the
1203* requested OEM JTAG Hash key
1204* Retries if compare fails
1205*
1206* Input:
1207* pUserFuseBurnStatus - pointer to a buffer containing a FuseBurnStatus structure
1208*
1209* Output:
1210* none
1211* Returns:
1212* NoError
1213* FUSE_BurnError
1214*
1215************************************************************/
1216UINT_T GEU_BurnFuseBlock_OemJtagHashKey(struct GEU_FuseBurnStatus * pUserFuseBurnStatus)
1217{
1218 UINT_T temp[8]; // temp buffer for fuse block compares
1219 UINT_T status;
1220
1221 // Confirm this fuseblock is active
1222 if (pActiveFuseData->ActiveFuseBlock != K_JTAG_FUSEBLOCK)
1223 {
1224 return (FUSE_FuseBlockNotActive);
1225 }
1226 // Confirm bandgap from USB PHY is enabled for the fuse power regulator
1227 if( _geuConfirmPowerEnabledForFuseBurning() == 0)
1228 {
1229 pFuseBurnStatus->FinalBurnStatus = FUSE_FuseBurnPowerNotEnabled;
1230 return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus->FinalBurnStatus));
1231 }
1232
1233 // Save the burn request in the FuseBurnStatus
1234 pFuseBurnStatus->SavedBurnRequest = pActiveFuseData->BurnRequest;
1235
1236 if ((pActiveFuseData->BurnRequest & K_JTAG_KEY0_BURN_REQUEST_MASK) == 0)
1237 {
1238 return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, FUSE_NoBurnRequest));
1239 }
1240
1241 // Burn Count = 0
1242 pActiveFuseData->BurnCount = 0;
1243
1244 while (pActiveFuseData->BurnRequest)
1245 {
1246 //++ ****** Burn **********
1247 status = _geuBurnFuse(K_JTAG_FUSEBLOCK, K_DO_NOT_LOCK_FUSEBLOCK); // Burn and NOT Lock JTAG Key Hash
1248 //-- ****** Burn **********
1249 if (status != 0)
1250 {
1251 pFuseBurnStatus->DebugStatus = status;
1252 }
1253
1254 // Burn Count++
1255 pActiveFuseData->BurnCount++;
1256 if (pActiveFuseData->BurnCount > 1)
1257 {
1258 pFuseBurnStatus->DebugStatus |= K_MULTIPLE_BURN_COUNT;
1259 }
1260
1261 //********************************************************************
1262 // Validate the JTAG Hash Burn
1263 //********************************************************************
1264
1265 if ((pActiveFuseData->BurnRequest & K_JTAG_KEY0_BURN_REQUEST_MASK) != 0)
1266 {
1267 //Compare Burned value with Saved value
1268 status = GEU_ReadOemJtagHashKeyFuseBits(&temp[0], K_FUSEBLOCK_SIZE);
1269 status = _geu_compare(&pActiveFuseData->FuseBlockSave[0],
1270 &temp[0],
1271 K_FUSEBLOCK_SIZE);
1272 if (status == 0)
1273 {
1274 // AP Burn Good - Clear the Burn Request
1275 pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest
1276 & ~K_JTAG_KEY0_BURN_REQUEST_MASK;
1277 }
1278 else
1279 {
1280 // If the BurnCount is 1, leave the burn request set
1281 // for another try.
1282 // Else
1283 if (pActiveFuseData->BurnCount >= 2)
1284 {
1285 // Burn Failed two times - Clear the burn Request
1286 pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest
1287 & ~K_JTAG_KEY0_BURN_REQUEST_MASK;
1288 // Set the AP Raw Burn Status to indicate Failure
1289 pFuseBurnStatus->RawBurnStatus = pFuseBurnStatus->RawBurnStatus |
1290 K_JTAG_KEY0_STATUS_BIT_MASK;
1291 }
1292 }//EndIfElse
1293 }//Endif
1294 }//End While
1295 // Set status
1296 pFuseBurnStatus->CorrectedBurnStatus = pFuseBurnStatus->RawBurnStatus;
1297 pFuseBurnStatus->FinalBurnStatus = NoError;
1298 if(pFuseBurnStatus->CorrectedBurnStatus != 0)
1299 {
1300 pFuseBurnStatus->FinalBurnStatus = FUSE_BurnError;
1301 }
1302
1303 return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus->FinalBurnStatus));
1304}//End Routine GEU_BurnFuseBlock_JTAG_Hash
1305
1306
1307
1308/**********************************************************
1309* Function:
1310* GEU_BurnEcc
1311*
1312* Description:
1313* This function burns an ECC value for an ECC protected field.
1314* This function must be called immediately after burning an ECC protected field.
1315* Notes:
1316* - GEU_SetActiveFuseblock must not be called between burning the ECC protected
1317* field and burning the ECC.
1318* - A read of any fuseblock field may occur between burning the ECC protected
1319* field and burning the ECC.
1320*
1321* This function first determines which ECC field must be burned based
1322* on the saved burn request in the FuseData structure.
1323*
1324* - Clears GEU_FUSE_PROG_VAL1 and VAL2 register sets.
1325* - Retrieves the saved ECC value from the last burn
1326* - and stores the ECC value in the appropriate field.
1327* - Burns the fuseblock
1328* - Validates all ECC fields using GEU_ECC_STATUS and checking
1329* for uncorrectable errors.
1330* - Retries the burn if compare fails
1331*
1332* Input:
1333* pUserFuseBurnStatus - pointer to a buffer containing a FuseBurnStatus structure
1334*
1335* Output:
1336* none
1337* Returns:
1338* NoError
1339* FUSE_BurnError
1340*
1341************************************************************/
1342UINT_T GEU_BurnECC(struct GEU_FuseBurnStatus * pUserFuseBurnStatus)
1343{
1344 UINT_T scratch, status;
1345
1346 if( _geuConfirmPowerEnabledForFuseBurning() == 0)
1347 {
1348 pFuseBurnStatus->FinalBurnStatus = FUSE_FuseBurnPowerNotEnabled;
1349 return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus->FinalBurnStatus));
1350 }
1351
1352
1353 // Do common chores for all ECC burns
1354 // Clear the FinalBurnStatus
1355 pFuseBurnStatus->FinalBurnStatus = NoError;
1356
1357 //Identify which ECC field to burn and set the ECC burn request for that field
1358 //++ Check first for ApCpUsb - all three burn requests must have been set
1359 // if ((pFuseBurnStatus->SavedBurnRequest & K_APCPUSB_BURN_REQUEST_MASK) != 0)
1360 // {
1361 // // Must have all three AP/CP/USB fields burned to proceed with ECC burn request
1362 // if ((pFuseBurnStatus->SavedBurnRequest & K_APCPUSB_BURN_REQUEST_MASK) != K_APCPUSB_BURN_REQUEST_MASK)
1363 // {
1364 // // All three fields not burned
1365 // return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, FUSE_IncompleteBurnRequest));
1366 // }
1367 // else
1368 // {
1369 // // Set ApCpUsb ECC burn request
1370 // pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest |
1371 // K_APCPUSB_ECC_BURN_REQUEST_MASK;
1372 // }
1373 // }//--Endif ApCpUsb burn check
1374
1375 //++ Check if OEM burn request was set
1376 if ((pFuseBurnStatus->SavedBurnRequest & K_OEM_KEY0_BURN_REQUEST_MASK) ==
1377 K_OEM_KEY0_BURN_REQUEST_MASK)
1378 {
1379 // Set OEM ECC burn request
1380 pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest |
1381 K_OEM_KEY0_ECC_BURN_REQUEST_MASK;
1382 }//--Endif OEM burn check
1383
1384 //++ Check if JTAG burn request was set
1385 if ((pFuseBurnStatus->SavedBurnRequest & K_JTAG_KEY0_BURN_REQUEST_MASK) ==
1386 K_JTAG_KEY0_BURN_REQUEST_MASK)
1387 {
1388 // Set JTAG ECC burn request
1389 pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest |
1390 K_JTAG_KEY0_ECC_BURN_REQUEST_MASK;
1391 }//-- Endif JTAG burn check
1392
1393 // Save the burn request in the FuseBurnStatus
1394 // This clears out the previous burn request
1395
1396 pFuseBurnStatus->SavedBurnRequest = pActiveFuseData->BurnRequest;
1397
1398 if ((pActiveFuseData->BurnRequest & (//K_APCPMP0_ECC_BURN_REQUEST_MASK |
1399 K_OEM_KEY0_ECC_BURN_REQUEST_MASK |
1400 K_JTAG_KEY0_ECC_BURN_REQUEST_MASK)) == 0)
1401 {
1402 return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, FUSE_NoBurnRequest));
1403 }
1404 // We have a legitimate ECC burn request
1405
1406 // Clear VAL1/VAL2 regster sets
1407 _geuClearVal1Val2RegisterSets();
1408
1409// _geuSaveAllFieldsInFuseBlock0NotBeingBurned();
1410
1411 // Move ECC to VAL1/VAL2 in proper offset
1412 // Only ONE burn request should be set as the EccCal register
1413 // is only valid for ONE fuseblock at a time
1414
1415 // // If ApCpUsb ECC burn request
1416 // if ((pActiveFuseData->BurnRequest & K_APCPUSB_ECC_BURN_REQUEST_MASK)!= 0)
1417 // {
1418 // // Save ApCpUsb ECC value to Val1/Val2
1419 // //_geuUpdateRegister(GEU_FUSE_PROG_VAL1+8, pActiveFuseData->EccCalRegSave, 0x0000FFFF);
1420 // scratch = pActiveFuseData->EccCalRegSave & 0x0000FFFF;
1421 // scratch = scratch << 16; // Shift ECC value to upper 16 bits
1422 // _geuUpdateRegister(GEU_FUSE_PROG_VAL2+12, scratch, 0XFFFF0000); // write to upper 16 bits of fuse block
1423
1424 // }
1425
1426
1427 // If OEM ECC burn request
1428 if ((pActiveFuseData->BurnRequest & K_OEM_KEY0_ECC_BURN_REQUEST_MASK)!= 0)
1429 {
1430 // Save OEM ECC value to Val1/Val2
1431 _geuUpdateRegister(GEU_FUSE_PROG_VAL1+12, pActiveFuseData->EccCalRegSave, 0xFFFFFFFF);
1432 pActiveFuseData->OemEccSave = pActiveFuseData->EccCalRegSave; // saved ECC value.
1433 }
1434 // If JTAG ECC burn request
1435 if ((pActiveFuseData->BurnRequest & K_JTAG_KEY0_ECC_BURN_REQUEST_MASK)!= 0)
1436 {
1437 // Save JTAG ECC value to Val1/Val2
1438 _geuUpdateRegister(GEU_FUSE_PROG_VAL2+0, pActiveFuseData->EccCalRegSave, 0xFFFFFFFF);
1439 pActiveFuseData->JtagEccSave = pActiveFuseData->EccCalRegSave; // saved ECC value.
1440 }
1441 // VAL1/VAL2 Registers updated
1442 // Burn Count = 0
1443 pActiveFuseData->EccBurnCount = 0;
1444
1445 _geuSaveAllFieldsInFuseBlock7NotBeingBurned();
1446
1447 while (pActiveFuseData->BurnRequest)
1448 {
1449 //++ ****** Burn **********
1450 status = _geuBurnFuse(K_FB7_FUSEBLOCK, 0);
1451 //-- ****** Burn **********
1452 if (status != 0)
1453 {
1454 pFuseBurnStatus->DebugStatus = status;
1455 }
1456
1457 // Burn Count++
1458 pActiveFuseData->EccBurnCount++;
1459 if (pActiveFuseData->BurnCount > 1)
1460 {
1461 pFuseBurnStatus->DebugStatus |= K_MULTIPLE_BURN_COUNT;
1462 }
1463
1464 //********************************************************************
1465 // Validate the component burned (one with a burn request)
1466 //********************************************************************
1467 // Validate Ecc Burn Request
1468 //********************************************************************
1469 //++
1470 // if ((pActiveFuseData->BurnRequest & K_APCPUSB_ECC_BURN_REQUEST_MASK) != 0)
1471 // {
1472 // // Check for ApCpUsb ECC Errors
1473 // GEU_REG_READ(GEU_ECC_STATUS, scratch);
1474 // pFuseBurnStatus->ApCpUsb_EccStatus = scratch &
1475 // K_APCPUSB_UNCORRECTABLE_ECC_ERROR_MASK;
1476 // if (pFuseBurnStatus->ApCpUsb_EccStatus == 0)
1477 // {
1478 // // ApCpUsb ECC Burn Good (No Errors or 1 Correctable error)
1479 // // - Clear the Burn Request
1480 // pActiveFuseData->BurnRequest &= ~K_APCPUSB_ECC_BURN_REQUEST_MASK;
1481 // // Clear any error reported in the CorrectedBurnStatus
1482 // pFuseBurnStatus->CorrectedBurnStatus &= ~K_APCPUSB_BURN_REQUEST_MASK;
1483 // }
1484 // else
1485 // {
1486 // // If the BurnCount is 1, leave the burn request set
1487 // // for another try.
1488 // // Else
1489 // if (pActiveFuseData->BurnCount >= 2)
1490 // {
1491 // // Ecc Burn Failed two times - Clear the burn Request
1492 // pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest
1493 // & ~K_APCPUSB_ECC_BURN_REQUEST_MASK;
1494 // // Set the Corrected Burn Status to indicate Failure
1495 // pFuseBurnStatus->CorrectedBurnStatus = pFuseBurnStatus->CorrectedBurnStatus |
1496 // K_APCPUSB_ECC_STATUS_BIT_MASK;
1497 // }
1498 // }//EndIfElse
1499 // }//Endif
1500 // //-- Validate ApCpUsb ECC Burn Request
1501
1502 //********************************************************************
1503 // Validate OEM ECC Burn Request
1504 //********************************************************************
1505 //++
1506 if ((pActiveFuseData->BurnRequest & K_OEM_KEY0_ECC_BURN_REQUEST_MASK) != 0)
1507 {
1508 // Check for ApCpUsb ECC Errors
1509 GEU_REG_READ(GEU_ECC_STATUS, scratch);
1510 pFuseBurnStatus->Oem_EccStatus = scratch &
1511 K_OEM_KEY_HASH0_UNCORRECTABLE_ECC_ERROR_MASK;
1512 if (pFuseBurnStatus->Oem_EccStatus == 0)
1513 {
1514 // OEM Platform Hash Key ECC Burn Good (No Errors or 1 Correctable error)
1515 // - Clear the Burn Request
1516 pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest
1517 & ~K_OEM_KEY0_ECC_BURN_REQUEST_MASK;
1518 // Clear any error in the CorrectedBurnStatus
1519 pFuseBurnStatus->CorrectedBurnStatus = pFuseBurnStatus->CorrectedBurnStatus
1520 & ~K_OEM_KEY0_BURN_REQUEST_MASK;
1521
1522 // Save OEM KEY ECC
1523 GEU_REG_READ(GEU_FUSE_VAL_OEM_KEY_ECC, pActiveFuseData->OemEccSave);
1524 }
1525 else
1526 {
1527 // If the EccBurnCount is 1, leave the burn request set
1528 // for another try.
1529 // Else
1530 if (pActiveFuseData->EccBurnCount >= 2)
1531 {
1532 // Ecc Burn Failed two times - Clear the burn Request
1533 pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest
1534 & ~K_OEM_KEY0_ECC_BURN_REQUEST_MASK;
1535 // Set the Corrected Burn Status to indicate Failure
1536 pFuseBurnStatus->CorrectedBurnStatus = pFuseBurnStatus->CorrectedBurnStatus |
1537 K_OEM_KEY0_ECC_STATUS_BIT_MASK;
1538 }
1539 }//EndIfElse
1540 }//Endif
1541 //-- Validate OEM ECC Burn Request
1542 //********************************************************************
1543 // Validate JTAG ECC Burn Request
1544 //********************************************************************
1545 //++
1546 if ((pActiveFuseData->BurnRequest & K_JTAG_KEY0_ECC_BURN_REQUEST_MASK) != 0)
1547 {
1548 // Check for JTAG ECC Errors
1549 GEU_REG_READ(GEU_ECC_STATUS, scratch);
1550 pFuseBurnStatus->Jtag_EccStatus = scratch &
1551 K_JTAG_KEY_HASH0_UNCORRECTABLE_ECC_ERROR_MASK;
1552 if (pFuseBurnStatus->Jtag_EccStatus == 0)
1553 {
1554 // JTAG ECC Burn Good (No Errors or 1 Correctable error)
1555 // - Clear the Burn Request
1556 pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest
1557 & ~K_JTAG_KEY0_ECC_BURN_REQUEST_MASK;
1558 // Clear any error in the CorrectedBurnStatus
1559 pFuseBurnStatus->CorrectedBurnStatus = pFuseBurnStatus->CorrectedBurnStatus
1560 & ~K_JTAG_KEY0_BURN_REQUEST_MASK;
1561
1562 // Save JTAG ECC
1563 GEU_REG_READ(GEU_FUSE_VAL_OEM_JTAG_KEY_HASH_ECC,pActiveFuseData->JtagEccSave);
1564 }
1565 else
1566 {
1567 // If the EccBurnCount is 1, leave the burn request set
1568 // for another try.
1569 // Else
1570 if (pActiveFuseData->EccBurnCount >= 2)
1571 {
1572 // Ecc Burn Failed two times - Clear the burn Request
1573 pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest
1574 & ~K_JTAG_KEY0_ECC_BURN_REQUEST_MASK;
1575 // Set the Corrected Burn Status to indicate Failure
1576 pFuseBurnStatus->CorrectedBurnStatus = pFuseBurnStatus->CorrectedBurnStatus |
1577 K_JTAG_KEY0_ECC_STATUS_BIT_MASK;
1578 }
1579 }//EndIfElse
1580 }//Endif
1581 //-- Validate JTAG ECC Burn Request
1582 }//End while
1583
1584 // //********************************************************************
1585 // // Validate fields NOT burned - Make sure they didn't change
1586 // //********************************************************************
1587 // //++ ApCpUsb ECC
1588 // if ((pFuseBurnStatus->SavedBurnRequest & K_APCPUSB_ECC_BURN_REQUEST_MASK) == 0)
1589 // {
1590 // status = _geuValidate_ApCpUsbId_ECC_FuseBits();
1591 // }
1592
1593 //++ OEM ECC
1594 if ((pFuseBurnStatus->SavedBurnRequest & K_OEM_KEY0_ECC_BURN_REQUEST_MASK) == 0)
1595 {
1596 status = _geuValidate_OEMHashKey_ECC_FuseBits();
1597 }
1598
1599 //++ JTAG ECC
1600 if ((pFuseBurnStatus->SavedBurnRequest & K_JTAG_KEY0_ECC_BURN_REQUEST_MASK) == 0)
1601 {
1602 status = _geuValidate_JTAGHashKey_ECC_FuseBits();
1603 }
1604 // status = _geuValidateApConfigFuseBits();
1605 // status = _geuValidateCpConfigFuseBits();
1606 status = _geuValidateUsbIdFuseBits();
1607 status = _geuValidateSecurityConfigFuseBits();
1608 // status = _geuValidateLifeCycleFuseBits();
1609 // status = _geuValidateSoftwareVersionFuseBits();
1610
1611 if(pFuseBurnStatus->CorrectedBurnStatus != 0)
1612 {
1613 pFuseBurnStatus->FinalBurnStatus = FUSE_BurnError;
1614 }
1615 else
1616 {
1617 pFuseBurnStatus->FinalBurnStatus = NoError;
1618 }
1619 return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus->FinalBurnStatus));
1620}//End Routine GEU_BURN_ECC
1621
1622
1623/**********************************************************
1624* Function:
1625* GEU_LockFuseBlock
1626*
1627* Description:
1628* Wrapper for individual fuse block lock burn routines.
1629* Sets the active fuse block to the specified fuse block
1630* and calls the generic lock routine
1631*
1632* Input:
1633* n- Fuse block to be locked
1634 pUserFuseBurnStatus - pointer to a buffer containing a FuseBurnStatus structure
1635*
1636* Output:
1637* none
1638* Returns:
1639* NoError
1640* FUSE_BurnError
1641* FUSE_UnsupportedFuseBlock
1642*
1643************************************************************/
1644UINT_T GEU_LockFuseBlock(UINT_T n, struct GEU_FuseBurnStatus * pUserFuseBurnStatus)
1645{
1646 UINT_T status;
1647 if( _geuConfirmPowerEnabledForFuseBurning() == 0)
1648 {
1649 pFuseBurnStatus->FinalBurnStatus = FUSE_FuseBurnPowerNotEnabled;
1650 return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus->FinalBurnStatus));
1651 }
1652
1653 switch (n)
1654 {
1655 default:
1656 case (K_AP_CONFIG_FUSEBLOCK):
1657 {
1658 // Lock on FB0 not supported (although it should be there in hardware
1659 // - use sticky bit instead
1660 status = FUSE_UnsupportedFuseBlock;
1661 break;
1662 }
1663 case (K_OEM_FUSEBLOCK):
1664 case (K_JTAG_FUSEBLOCK):
1665 case (K_RKEK_FUSEBLOCK):
1666 case (K_FB7_FUSEBLOCK):
1667 {
1668 status = GEU_SetActiveFuseBlock(n);
1669 status = _geuLockActiveFuseblock(pUserFuseBurnStatus);
1670 break;
1671 }
1672 }//End Switch
1673 return status;
1674}//End Routine GEU_LOCK_FUSEBLOCK
1675
1676
1677UINT_T GEU_SetupSecurityConfigUsbIdEccFuseBits(void)
1678{
1679
1680 UINT_T ecc_cal;
1681
1682 /* Confirm this fuseblock is active */
1683 if (pActiveFuseData->ActiveFuseBlock != K_USBID_FUSEBLOCK) {
1684 return (FUSE_FuseBlockNotActive);
1685 }
1686
1687 if (pActiveFuseData->ActiveFuseBlockField != K_SECURITY_USBID_FUSEBLOCK_FIELD) {
1688 return (FUSE_FuseBlockFieldNotActive);
1689 }
1690
1691 //if ((pActiveFuseData->BurnRequest & K_SECURITY_USBID_BURN_REQUEST_MASK) != K_SECURITY_USBID_BURN_REQUEST_MASK) {
1692 // return FUSE_IncompleteFuseFieldsSetup;
1693 //}
1694
1695 GEU_REG_READ(GEU_ECC_CAL, ecc_cal);
1696
1697 _geuUpdateRegister(GEU_FUSE_PROG_VAL1 + 8, ecc_cal, 0xFF);
1698
1699 // Save to Active fuseblock for burn validation later
1700 pActiveFuseData->SecurityUsbEccSave = (ecc_cal & 0xFF);
1701
1702 pActiveFuseData->BurnRequest |= K_SECURITY_USBID_ECC_BURN_REQUEST_MASK;
1703
1704 return NoError;
1705}
1706
1707
1708/**********************************************************
1709* Function:
1710* GEU_BurnFuseBlock_SecurityUSBIDECC
1711*
1712* Description:
1713* Burns the Security config and USB ID field, and SecurityUSBECC in Fuseblock 7. This may burn one
1714* or more of the Security Config, and USB Id subfields and ECC
1715*
1716* - Confirms that a burn request exists for one or more of the
1717* Security or USB Id subfields or ECC.
1718* - Saves other state (for post burn validation).
1719* - Saves any of the the Security Config or USB Id subfields that are not being burned.
1720* - Burns the fuseblock
1721* Validates burned subfields and retries if burn not successful.
1722* - Validates all subfields that were not burned to ensure no changes from the burn.
1723*
1724* Input:
1725* pUserFuseBurnStatus - pointer to a buffer containing a FuseBurnStatus structure
1726*
1727* Output:
1728* none
1729* Returns:
1730* NoError
1731* FUSE_FuseBlockNotActive
1732* FUSE_FuseBurnPowerNotEnabled
1733* FUSE_NoBurnRequest
1734* FUSE_BurnError
1735*
1736************************************************************/
1737UINT_T GEU_BurnFuseBlock_SecurityUSBIDECC(struct GEU_FuseBurnStatus * pUserFuseBurnStatus)
1738{
1739 UINT_T temp[8]; // temp buffer for fuse block compares
1740 UINT_T status;
1741
1742 // Confirm this fuseblock is active
1743 if (pActiveFuseData->ActiveFuseBlock != K_USBID_FUSEBLOCK)
1744 {
1745 return (FUSE_FuseBlockNotActive);
1746 }
1747
1748 // Confirm bandgap from USB PHY is enabled for the fuse power regulator
1749 if( _geuConfirmPowerEnabledForFuseBurning() == 0)
1750 {
1751 pFuseBurnStatus->FinalBurnStatus = FUSE_FuseBurnPowerNotEnabled;
1752 return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus->FinalBurnStatus));
1753 }
1754
1755 // Save the burn request in the FuseBurnStatus
1756 pFuseBurnStatus->SavedBurnRequest = pActiveFuseData->BurnRequest;
1757
1758 if (pActiveFuseData->BurnRequest & (K_SECURITY_USBID_BURN_REQUEST_MASK | K_SECURITY_USBID_ECC_BURN_REQUEST_MASK) == 0)
1759 {
1760 return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, FUSE_IncompleteFuseFieldsSetup));
1761 }
1762
1763
1764
1765 // _geuSaveAllFieldsInFuseBlock7NotBeingBurned();
1766
1767 // Burn Count = 0
1768 //pActiveFuseData->ApCpUsbBurnCount = 0;
1769 pActiveFuseData->BurnCount = 0;
1770 while (pActiveFuseData->BurnRequest)
1771 {
1772 //++ ****** Burn **********
1773 status = _geuBurnFuse(K_USBID_FUSEBLOCK, 0);
1774 //-- ****** Burn **********
1775 if (status != 0)
1776 {
1777 pFuseBurnStatus->DebugStatus = status;
1778 }
1779 // Burn Count++
1780 pActiveFuseData->BurnCount++;
1781 if (pActiveFuseData->BurnCount > 1)
1782 {
1783 pFuseBurnStatus->DebugStatus |= K_MULTIPLE_BURN_COUNT;
1784 }
1785
1786 //********************************************************************
1787 // Validate the components burned (ones with a burn request)
1788 //********************************************************************
1789 // Validate Security CONFIG Burn Request
1790 //********************************************************************
1791 //++
1792 if ((pActiveFuseData->BurnRequest & K_SECURITY_CONFIG_BURN_REQUEST_MASK) != 0)
1793 {
1794 //Compare Burned Security with Saved Security Config Bits
1795 status = GEU_ReadSecurityConfigFuseBits(&temp[0],
1796 K_SECURITY_CONFIG_FUSE_SIZE);
1797 // Ignore status - whatever we read, we read
1798 status = _geu_compare(&pActiveFuseData->SecurityConfigSave[0],
1799 &temp[0],
1800 K_SECURITY_CONFIG_FUSE_SIZE);
1801 if (status == 0)
1802 {
1803 // Security Config Burn Good - Clear the Burn Request
1804 pActiveFuseData->BurnRequest &= ~K_SECURITY_CONFIG_BURN_REQUEST_MASK;
1805
1806 }
1807 else
1808 {
1809 // If the BurnCount is 1, leave the burn request set
1810 // for another try.
1811 // Else
1812 if (pActiveFuseData->BurnCount >= 2)
1813 {
1814 // Security Burn Failed two times - Clear the burn Request
1815 pActiveFuseData->BurnRequest &= ~K_SECURITY_CONFIG_BURN_REQUEST_MASK;
1816 // Set the Security Raw Burn Status to indicate Failure
1817 pFuseBurnStatus->RawBurnStatus |= K_SECURITY_CONFIG_BURN_REQUEST_MASK;
1818 }
1819
1820 }//EndIfElse
1821
1822 }//Endif
1823 //-- Validate Security CONFIG Burn Request
1824
1825 //********************************************************************
1826 // Validate USB ID Burn Request
1827 //********************************************************************
1828 //++
1829 if ((pActiveFuseData->BurnRequest & K_USBID_BURN_REQUEST_MASK) != 0)
1830 {
1831 //Compare Burned USB with Saved USB Config Bits
1832 status = GEU_ReadUsbIdFuseBits(&temp[0],
1833 K_USBID_FUSE_SIZE);
1834 status = _geu_compare(&pActiveFuseData->UsbIdSave[0],
1835 &temp[0],
1836 K_USBID_FUSE_SIZE);
1837 if (status == 0)
1838 {
1839 // USB Burn Good - Clear the Burn Request
1840 pActiveFuseData->BurnRequest &= ~K_USBID_BURN_REQUEST_MASK;
1841
1842 }
1843 else
1844 {
1845 // If the BurnCount is 1, leave the burn request set
1846 // for another try.
1847 // Else
1848 if (pActiveFuseData->BurnCount >= 2)
1849 {
1850
1851 // USB ID Burn Failed two times - Clear the Burn Request
1852 pActiveFuseData->BurnRequest &= ~K_USBID_BURN_REQUEST_MASK;
1853
1854 // Set theUSB ID Raw Burn Status to indicate Failure
1855 pFuseBurnStatus->RawBurnStatus |= K_USBID_STATUS_BIT_MASK;
1856 }
1857
1858 }//EndIfElse
1859
1860 }//Endif
1861 // Validate Security USB ECC
1862 if ((pActiveFuseData->BurnRequest & K_SECURITY_USBID_ECC_BURN_REQUEST_MASK) != 0)
1863 {
1864 UINT_T ecc;
1865 GEU_REG_READ(GEU_FUSE_VAL_SECURITY_USB_ECC, ecc);
1866 status = _geu_compare(&pActiveFuseData->SecurityUsbEccSave,
1867 &ecc,
1868 K_SECURITY_USB_ECC_FUSE_SIZE);
1869
1870 if (status == 0)
1871 {
1872 // Security USB Ecc Burn Good - Clear the Burn Request
1873 pActiveFuseData->BurnRequest &= ~K_SECURITY_USBID_ECC_BURN_REQUEST_MASK;
1874
1875 }
1876 else
1877 {
1878 // If the BurnCount is 1, leave the burn request set
1879 // for another try.
1880 // Else
1881 if (pActiveFuseData->BurnCount >= 2)
1882 {
1883
1884 // Security USB Ecc Burn Failed two times - Clear the Burn Request
1885 pActiveFuseData->BurnRequest &= ~K_SECURITY_USBID_ECC_BURN_REQUEST_MASK;
1886
1887 // Set the Security USB Ecc Raw Burn Status to indicate Failure
1888 pFuseBurnStatus->RawBurnStatus |= K_SECURITY_USBID_ECC_BURN_REQUEST_MASK;
1889 }
1890
1891 }//EndIfElse
1892 }
1893 //-- Validate Security USB Ecc Request
1894 }//End While
1895
1896 //
1897 // All of the components of the Security Config and USB ID fields that were SETUP, have been burned.
1898 // we are done Burning Fuse Block 7.
1899 //
1900
1901 // Now Validate components in the Fuse Block 7 (AP/CP/MP/LC/etc group without burn request
1902 // to verify that they did not change.
1903 // The BurnRequest bits in the ActiveFuseData have been cleared by now so use the saved copy
1904 // of the Burn Request in the FuseBurnStatus.
1905
1906 // Security Config
1907 if ((pFuseBurnStatus->SavedBurnRequest & K_SECURITY_CONFIG_BURN_REQUEST_MASK) == 0)
1908 {
1909 //Compare FuseBlock Security Config bits with Saved Security Config Bits
1910 status = _geuValidateSecurityConfigFuseBits();
1911 }
1912
1913 // USB ID
1914 if ((pFuseBurnStatus->SavedBurnRequest & K_USBID_BURN_REQUEST_MASK) == 0)
1915 {
1916 //Compare FuseBlock USB ID bits with Saved USB ID Bits
1917 status = _geuValidateUsbIdFuseBits();
1918 }
1919
1920 //++ OEM ECC
1921 if ((pFuseBurnStatus->SavedBurnRequest & K_OEM_KEY0_ECC_BURN_REQUEST_MASK) == 0)
1922 {
1923 status = _geuValidate_OEMHashKey_ECC_FuseBits();
1924 }
1925
1926 //++ JTAG ECC
1927 if ((pFuseBurnStatus->SavedBurnRequest & K_JTAG_KEY0_ECC_BURN_REQUEST_MASK) == 0)
1928 {
1929 status = _geuValidate_JTAGHashKey_ECC_FuseBits();
1930 }
1931
1932 // Set status
1933 pFuseBurnStatus->CorrectedBurnStatus = pFuseBurnStatus->RawBurnStatus;
1934 if(pFuseBurnStatus->CorrectedBurnStatus != 0)
1935 {
1936 pFuseBurnStatus->FinalBurnStatus = FUSE_BurnError;
1937 }
1938 return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus->FinalBurnStatus));
1939}//End Routine GEU_BurnFuseBlock_SecurityUSBID
1940
1941
1942
1943/**********************************************************
1944* Function:
1945* _geuLockActiveFuseBlock
1946*
1947* Description:
1948* Generic fuse block lock routines.
1949*
1950* - Saves the active fuse block data
1951* - Clears VAL1 and VAL2 register sets
1952* - Sets the Lock burn request
1953* - Burns the fuse block with the Fuse Lock set
1954* - Validates the lock gets set
1955* - Will retry if necessary
1956* - Validates fuse block data did not change
1957*
1958* Input:
1959* pUserFuseBurnStatus - pointer to a buffer containing a FuseBurnStatus structure
1960*
1961* Output:
1962* none
1963* Returns:
1964* NoError
1965* FUSE_BurnError
1966* FUSE_UnsupportedFuseBlock
1967*
1968************************************************************/
1969UINT_T _geuLockActiveFuseblock(struct GEU_FuseBurnStatus * pUserFuseBurnStatus)
1970{
1971 UINT_T temp[8]; // temp buffer for fuse block compare
1972 UINT_T scratch;
1973 UINT_T status;
1974 UINT_T RawFailureBitMask;
1975
1976 switch(pActiveFuseData->ActiveFuseBlock)
1977 {
1978 case(K_OEM_FUSEBLOCK):
1979 {// Save OEM Hash
1980 status = GEU_ReadOemHashKeyFuseBits(&pActiveFuseData->FuseBlockSave[0], K_FUSEBLOCK_SIZE);
1981 break;
1982 }
1983 case(K_JTAG_FUSEBLOCK):
1984 {// Save JTAG Hash
1985 status = GEU_ReadOemJtagHashKeyFuseBits(&pActiveFuseData->FuseBlockSave[0], K_FUSEBLOCK_SIZE);
1986 break;
1987 }
1988 case(K_RKEK_FUSEBLOCK):
1989 {// Save RKEK Hash
1990 //status = GEU_ReadRkekFuseBits(&pActiveFuseData->FuseBlockSave[0], K_FUSEBLOCK_SIZE);
1991 break;
1992 }
1993 case(K_ECC_FUSEBLOCK):
1994 {// Save ECC values
1995 GEU_REG_READ(GEU_FUSE_VAL_APCP_ECC, pActiveFuseData->ApCpMpEccSave);
1996 GEU_REG_READ(GEU_FUSE_VAL_OEM_KEY_ECC, pActiveFuseData->OemEccSave);
1997 GEU_REG_READ(GEU_FUSE_VAL_OEM_JTAG_KEY_HASH_ECC,pActiveFuseData->JtagEccSave);
1998 break;
1999 }
2000 default:
2001 {
2002 return (FUSE_UnsupportedFuseBlock);
2003 }
2004 }//End switch
2005
2006 // Clear VAL1 & VAL2 register sets
2007 _geuClearVal1Val2RegisterSets();
2008
2009 //Set the burn request
2010 pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest | K_FUSEBLOCK_LOCK_BURN_REQUEST_MASK;
2011
2012 pActiveFuseData->BurnCount = 0;
2013
2014 while (pActiveFuseData->BurnRequest)
2015 {
2016 //++ ****** Burn **********
2017 status = _geuBurnFuse(pActiveFuseData->ActiveFuseBlock, K_LOCK_FUSEBLOCK);
2018 //-- ****** Burn **********
2019 if (status != 0)
2020 {
2021 pFuseBurnStatus->DebugStatus = status;
2022 }
2023
2024 // Burn Count++
2025 pActiveFuseData->BurnCount++; // BurnCount or LockBurnCount?
2026 if (pActiveFuseData->BurnCount > 1)
2027 {
2028 pFuseBurnStatus->DebugStatus |= K_MULTIPLE_BURN_COUNT;
2029 }
2030
2031 // Validate block locked
2032 GEU_REG_READ(GEU_FUSE_STATUS, scratch);
2033 scratch = (scratch & GEU_FUSE_STATUS_LOCK_BIT_MSK)>>GEU_FUSE_STATUS_LOCK_BIT_BASE;
2034 scratch = scratch & pActiveFuseData->FuseLockBitMask;
2035
2036 if (scratch != 0)
2037 {
2038 // Burn Good - Clear the Burn Request
2039 pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest
2040 & ~K_FUSEBLOCK_LOCK_BURN_REQUEST_MASK;
2041 }
2042 else
2043 {
2044 // Burn failed
2045 // If the BurnCount is 1, leave the burn request set
2046 // for another try.
2047 // Else
2048 if (pActiveFuseData->BurnCount >= 2)
2049 {
2050 // Burn Failed two times - Clear the burn Request
2051 pActiveFuseData->BurnRequest = pActiveFuseData->BurnRequest
2052 & ~K_FUSEBLOCK_LOCK_BURN_REQUEST_MASK;
2053 // Set the AP Raw Burn Status to indicate Failure
2054 pFuseBurnStatus->RawBurnStatus = pFuseBurnStatus->RawBurnStatus |
2055 K_LOCK_STATUS_BIT_MASK;
2056 }
2057 }//EndIfElse
2058
2059 }//End while
2060 switch(pActiveFuseData->ActiveFuseBlock)
2061 {
2062 case(K_OEM_FUSEBLOCK):
2063 {// Save OEM Hash
2064 status = GEU_ReadOemHashKeyFuseBits(&temp[0], K_FUSEBLOCK_SIZE);
2065 status = _geu_compare(&pActiveFuseData->FuseBlockSave[0],
2066 &temp[0],
2067 K_FUSEBLOCK_SIZE);
2068 RawFailureBitMask = K_OEM_KEY0_STATUS_BIT_MASK;
2069 break;
2070 }
2071 case(K_JTAG_FUSEBLOCK):
2072 {// Save JTAG Hash
2073 status = GEU_ReadOemJtagHashKeyFuseBits(&temp[0], K_FUSEBLOCK_SIZE);
2074 status = _geu_compare(&pActiveFuseData->FuseBlockSave[0],
2075 &temp[0],
2076 K_FUSEBLOCK_SIZE);
2077 RawFailureBitMask = K_JTAG_KEY0_STATUS_BIT_MASK;
2078 break;
2079 }
2080 case(K_RKEK_FUSEBLOCK):
2081 {// Save RKEK Hash
2082 //status = GEU_ReadRkekFuseBits(&temp[0], K_FUSEBLOCK_SIZE);
2083 //status = _geu_compare(&pActiveFuseData->FuseBlockSave[0],
2084 // &temp[0],
2085 // K_FUSEBLOCK_SIZE);
2086 //RawFailureBitMask = K_RKEK_STATUS_BIT_MASK;
2087 break;
2088 }
2089 case(K_ECC_FUSEBLOCK):
2090 {// Save ECC values
2091 status = 0;
2092 GEU_REG_READ(GEU_FUSE_VAL_APCP_ECC, temp[0]);
2093 if (pActiveFuseData->ApCpMpEccSave != temp[0])
2094 {
2095 status = FUSE_FuseBlockCompareFailed ;
2096 RawFailureBitMask = K_APCPMP0_ECC_STATUS_BIT_MASK;
2097 }
2098 GEU_REG_READ(GEU_FUSE_VAL_OEM_KEY_ECC, temp[0]);
2099 if (pActiveFuseData->OemEccSave != temp[0])
2100 {
2101 status = FUSE_FuseBlockCompareFailed ;
2102 RawFailureBitMask = K_OEM_KEY0_ECC_STATUS_BIT_MASK;
2103 }
2104 GEU_REG_READ(GEU_FUSE_VAL_OEM_JTAG_KEY_HASH_ECC, temp[0]);
2105 if (pActiveFuseData->JtagEccSave != temp[0])
2106 {
2107 status = FUSE_FuseBlockCompareFailed ;
2108 RawFailureBitMask = K_JTAG_KEY0_ECC_STATUS_BIT_MASK;
2109 }
2110 break;
2111 }//End Case
2112 default:
2113 {
2114 return (FUSE_UnsupportedFuseBlock);
2115 }
2116 }//End switch
2117 if (status != 0)
2118 {
2119 pFuseBurnStatus->RawBurnStatus = pFuseBurnStatus->RawBurnStatus |
2120 RawFailureBitMask;
2121 }
2122 pFuseBurnStatus->CorrectedBurnStatus = pFuseBurnStatus->RawBurnStatus;
2123 if(pFuseBurnStatus->CorrectedBurnStatus != 0)
2124 {
2125 pFuseBurnStatus->FinalBurnStatus = FUSE_BurnError;
2126 }
2127
2128 return(_geuUpdateUserFuseBurnStatus(pUserFuseBurnStatus, pFuseBurnStatus->FinalBurnStatus));
2129
2130}// End Routine _geuLockActiveFuseblock
2131
2132
2133UINT_T _geuValidateUsbIdFuseBits()
2134{
2135 UINT_T temp[8]; // temp buffer for fuse block compares
2136 UINT_T status = NoError;
2137
2138 //++ ***** Validate USB Id bits did not change ******************
2139 //Compare FuseBlock USB ID bits with Saved USB ID Bits
2140 status = GEU_ReadUsbIdFuseBits(&temp[0],
2141 K_USBID_FUSE_SIZE);
2142 status = _geu_compare(&pActiveFuseData->UsbIdSave[0],
2143 &temp[0],
2144 K_USBID_FUSE_SIZE);
2145 if (status != 0)
2146 {
2147 // Set the USB Raw Burn Status to indicate Failure
2148 pFuseBurnStatus->RawBurnStatus = pFuseBurnStatus->RawBurnStatus |
2149 K_USBID_STATUS_BIT_MASK;
2150 }
2151 return status;
2152}
2153
2154
2155
2156UINT_T _geuValidateSecurityConfigFuseBits()
2157{
2158 UINT_T temp[8]; // temp buffer for fuse block compares
2159 UINT_T status = NoError;
2160
2161 //++ ***** Validate Security Config bits did not change ******************
2162 //Compare FuseBlock Security ID bits with Saved USB ID Bits
2163 status = GEU_ReadSecurityConfigFuseBits(&temp[0],
2164 K_SECURITY_CONFIG_FUSE_SIZE);
2165 status = _geu_compare(&pActiveFuseData->SecurityConfigSave[0],
2166 &temp[0],
2167 K_SECURITY_CONFIG_FUSE_SIZE);
2168 if (status != 0)
2169 {
2170 // Set the USB Raw Burn Status to indicate Failure
2171 pFuseBurnStatus->RawBurnStatus = pFuseBurnStatus->RawBurnStatus |
2172 K_SECURITY_CONFIG_STATUS_BIT_MASK;
2173 }
2174 return status;
2175}
2176
2177
2178
2179UINT_T _geuValidate_OEMHashKey_ECC_FuseBits()
2180{
2181 UINT_T status = NoError;
2182 UINT_T CurrentEcc, EccStatus;
2183
2184 // OEM Hash Key ECC
2185 GEU_REG_READ(GEU_FUSE_VAL_OEM_KEY_ECC, CurrentEcc);
2186 if (pActiveFuseData->OemEccSave == 0)
2187 {
2188 // No ECC was burned so make sure it'still 0
2189 if (CurrentEcc !=0)
2190 {
2191 // Ecc Burn of some other field corrupted this ECC field
2192 // Set the Corrected Burn Status to indicate Failure
2193 pFuseBurnStatus->CorrectedBurnStatus |= K_OEM_KEY_HASH0_UNCORRECTABLE_ECC_ERROR_MASK;
2194 status = FUSE_FuseBlockCompareFailed;
2195 }
2196 }
2197 else
2198 {
2199 // Saved ECC value NOT zero
2200 // Confirm it didn't change
2201 if (pActiveFuseData->OemEccSave != CurrentEcc)
2202 {
2203 // Check the ECC status and see if it's still correctable
2204 GEU_REG_READ(GEU_ECC_STATUS, EccStatus);
2205 pFuseBurnStatus->Oem_EccStatus = EccStatus &
2206 K_OEM_KEY_HASH0_UNCORRECTABLE_ECC_ERROR_MASK;
2207 if (pFuseBurnStatus->Oem_EccStatus != 0)
2208 {
2209 // Ecc Burn Corrupted this ECC field with uncorrectable errors
2210 // Set the Corrected Burn Status to indicate Failure
2211 pFuseBurnStatus->CorrectedBurnStatus |= K_OEM_KEY0_ECC_STATUS_BIT_MASK;
2212 status = FUSE_FuseBlockCompareFailed;
2213 }//EndIf
2214 }
2215 }
2216 return status;
2217}
2218
2219UINT_T _geuValidate_JTAGHashKey_ECC_FuseBits()
2220{
2221 UINT_T status = NoError;
2222 UINT_T CurrentEcc, EccStatus;
2223
2224 GEU_REG_READ(GEU_FUSE_VAL_OEM_JTAG_KEY_HASH_ECC, CurrentEcc);
2225 if (pActiveFuseData->JtagEccSave == 0)
2226 {
2227 // No ECC was burned so make sure it'still 0
2228 if (CurrentEcc !=0)
2229 {
2230 // Ecc Burn of some other field corrupted this ECC field
2231 // Set the Corrected Burn Status to indicate Failure
2232 pFuseBurnStatus->CorrectedBurnStatus |= K_JTAG_KEY_HASH0_UNCORRECTABLE_ECC_ERROR_MASK;
2233 status = FUSE_FuseBlockCompareFailed;
2234 }
2235 }
2236 else
2237 {
2238 // Saved ECC value NOT zero
2239 // Confirm it didn't change
2240 if (pActiveFuseData->JtagEccSave != CurrentEcc)
2241 {
2242 // Check the ECC status and see if it's still correctable
2243 GEU_REG_READ(GEU_ECC_STATUS, EccStatus);
2244 pFuseBurnStatus->Jtag_EccStatus = EccStatus &
2245 K_JTAG_KEY_HASH0_UNCORRECTABLE_ECC_ERROR_MASK;
2246 if (pFuseBurnStatus->Jtag_EccStatus != 0)
2247 {
2248 // Ecc Burn Corrupted this ECC field with uncorrectable errors
2249 // Set the Corrected Burn Status to indicate Failure
2250 pFuseBurnStatus->CorrectedBurnStatus |= K_JTAG_KEY0_ECC_STATUS_BIT_MASK;
2251 status = FUSE_FuseBlockCompareFailed;
2252 }//EndIf
2253 }
2254 }
2255 return status;
2256}
2257
2258
2259
2260void _geuSaveAllFieldsInFuseBlock7NotBeingBurned()
2261{
2262 volatile UINT_T status = NoError;
2263
2264 // Save everything in the fuseblock(ApCpMpId ECC, JTAG ECC,OEM ECC,UsbId)
2265
2266 // Save LifeCycle
2267 pActiveFuseData->LifeCycleSave = GEU_ReadLifeCycle();
2268
2269
2270 //Save USB ID Bits
2271 if ((pActiveFuseData->BurnRequest & K_USBID_BURN_REQUEST_MASK) == 0)
2272 {
2273 status = GEU_ReadUsbIdFuseBits(&pActiveFuseData->UsbIdSave[0], K_USBID_FUSE_SIZE);
2274 }
2275 //Save Security Config ID Bits
2276 if ((pActiveFuseData->BurnRequest & K_SECURITY_USBID_BURN_REQUEST_MASK) == 0)
2277 {
2278 status = GEU_ReadSecurityConfigFuseBits(&pActiveFuseData->SecurityConfigSave[0], K_SECURITY_CONFIG_FUSE_SIZE);
2279 }
2280 //Save OEM UID Bits
2281 if ((pActiveFuseData->BurnRequest & K_OEM_UID_BURN_REQUEST_MASK) == 0)
2282 {
2283 status = GEU_ReadOemUidFuseBits(&pActiveFuseData->OemUidSave[0], K_OEM_UNIQUE_ID_FUSE_SIZE);
2284 }
2285
2286 // Save JTAG ECC
2287 GEU_REG_READ(GEU_FUSE_VAL_OEM_JTAG_KEY_HASH_ECC,pActiveFuseData->JtagEccSave);
2288
2289 // Save OEM KEY ECC
2290 GEU_REG_READ(GEU_FUSE_VAL_OEM_KEY_ECC, pActiveFuseData->OemEccSave);
2291
2292 // Save ApCpMpId ECC
2293 GEU_REG_READ(GEU_FUSE_VAL_APCP_ECC, pActiveFuseData->ApCpMpEccSave);
2294
2295 // Save LCS (JPD, FA, DD) and OEM UID ECC
2296 GEU_REG_READ(GEU_FUSE_VAL_LIFECYCLE_JPD_FA_DD_OEM_UID_ECC, pActiveFuseData->OemUidEccSave);
2297
2298
2299 return;
2300}
2301