1 /*******************************************************************************
2  * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * MPFS HAL Embedded Software
7  *
8  */
9 
10 /*******************************************************************************
11  * @file mss_sgmii.c
12  * @author Microchip-FPGA Embedded Systems Solutions
13  * @brief sgmii related functions
14  *
15  */
16 
17 #include <string.h>
18 #include <stdio.h>
19 #include "mpfs_hal/mss_hal.h"
20 #include "simulation.h"
21 
22 #ifdef  MPFS_HAL_HW_CONFIG
23 
24 static PART_TYPE silicon_variant = PART_NOT_DETERMINED;
25 
26 /*
27  * local functions
28  */
29 static void setup_sgmii_rpc_per_config(void);
30 #ifdef SGMII_SUPPORT
31 static uint32_t sgmii_channel_setup(void);
32 #endif
33 
34 /*
35  * local variable
36  */
37 static uint32_t sro_dll_90_code;
38 
39 /*
40  * local functions
41  */
42 static void set_early_late_thresholds(uint8_t n_late_threshold, uint8_t p_early_threshold);
43 
44 /*
45  * extern functions
46  */
47 extern void sgmii_mux_config(uint8_t option);
48 
49 
sgmii_setup(void)50 uint32_t sgmii_setup(void)
51 {
52 #ifdef SGMII_SUPPORT
53     /*
54      * Check if any tx/Rx channels enabled
55      */
56     if((LIBERO_SETTING_SGMII_MODE & (TX_RX_CH_EN_MASK<<TX_RX_CH_EN_OFFSET)) != 0U)
57     {
58         while (sgmii_channel_setup() != 0)
59         {
60 
61         }
62     }
63     else
64     {
65         sgmii_off_mode();
66         sgmii_mux_config(RPC_REG_UPDATE);
67     }
68 #else
69     {
70         sgmii_off_mode();
71         sgmii_mux_config(RPC_REG_UPDATE);
72     }
73 #endif
74     return(0UL);
75 }
76 
77 
78 /**
79  *
80  * @param sgmii_instruction
81  * @return
82  */
83 #ifdef SGMII_SUPPORT
sgmii_channel_setup(void)84 static uint32_t sgmii_channel_setup(void)
85 {
86     static SGMII_TRAINING_SM sgmii_training_state = SGMII_SETUP_INIT;
87     static uint32_t status = SGMII_IN_SETUP;
88     static uint32_t timer_out;
89 
90     /*
91      * Initialise NWC
92      *      Clocks
93      *      SGMII
94      *      DDR
95      *      IOMUX
96      */
97 
98     switch(sgmii_training_state)
99     {
100         case SGMII_SETUP_INIT:
101             status = SGMII_IN_SETUP;
102             CFG_DDR_SGMII_PHY->SOFT_RESET_SGMII.SOFT_RESET_SGMII = \
103                     (0x01 << 8U) | 1U; /* PERIPH   soft reset */
104             CFG_DDR_SGMII_PHY->SOFT_RESET_SGMII.SOFT_RESET_SGMII = 1U;
105             setup_sgmii_rpc_per_config();         /* load RPC SGMII_MODE register ext */
106 
107             /* Enable the Bank controller */
108             /*
109              * Set soft reset on IP to load RPC to SCB regs (dynamic mode)
110              * Bring the sgmii bank controller out of reset =- ioscb_bank_ctrl_sgmii
111              */
112             IOSCB_BANK_CNTL_SGMII->soft_reset = 1U;  /* DPC_BITS NV_MAP  reset */
113             sgmii_training_state = SGMII_IO_EN;
114             break;
115 
116         case SGMII_IO_EN:
117             /*
118              * Check the IO_EN signal here.
119              * This is an output from the bank controller power detector, which are
120              * turned on using MSS_IO_EN
121              */
122             /* aro_ioen_bnk  - PVT calibrator IOEN  */
123             timer_out++;
124             if((CFG_DDR_SGMII_PHY->PVT_STAT.PVT_STAT & (0x01U<<6U)) != 0U)
125             {
126                 timer_out=0U;
127                 sgmii_training_state = SGMII_RAMP_TIMER;
128             }
129             break;
130 
131         case SGMII_RAMP_TIMER:
132             /*
133              * IO power ramp wait time
134              * After IOEN is received from power detectors DDR and SGMii, extra time
135              * required for voltage to ramp.
136              * This time will come from the user- Dependent on ramp time of power
137              * supply
138              * Approximately - Bank power timer (from ioen_in to ioen_out = 10uS)?
139              *
140              */
141             timer_out++;
142             if(timer_out >= 0xFU)
143             {
144                 timer_out=0U;
145                 sgmii_training_state = SGMII_IO_SETUP;
146             }
147             break;
148 
149         case SGMII_IO_SETUP:
150             /*
151              * fixme- not sure if we should be setting this register
152              * From regmap detail:
153              * bit 8 of MSS_RESET_CR
154              * Asserts a reset the SGMII block containing the MSS reference clock
155              * input.
156              * Warning that setting this bit causes the external reference clock
157              * input to the
158              * MSS PLL to disappear.
159              * It is advisable to use the SGMII channel soft resets in the PHY
160              * instead of this bit.
161              * However if E51 software wants to set this bit, the MSS clock source
162              * should be switched over to the standby source in advance.
163              */
164             SCB_REGS->MSS_RESET_CR.MSS_RESET_CR = 0;
165 
166             /*
167              * I ran the sim past the place where we set the nvmap_reset in the
168              * SOFT_RESET_SGMII register and it did not result in any
169              * change from the DLL default bits.
170              * But I traced the 'flashing' signal on one of these regs back to
171              * 'dll0_soft_reset_nv_map' (not 'pll0_soft_reset_periph').
172              * Now the only place I can find 'dll0_soft_reset_nv_map' is in SCB
173              * space...ie 0x3e10_0000 SOFT_RESET register.
174              *
175              */
176             /*
177              * so we have to use scb register to reset as no APB register available
178              * to soft reset the IP
179              * ioscb_dll_sgmii
180              * */
181             IOSCB_DLL_SGMII->soft_reset = (0x01U << 0x00U);  /*  reset sgmii DLL */
182 
183             /*
184               * I have discovered the problem with the tx channels (soft reset issue)
185               * So we require the:
186               *
187               * sgmiiphy_lane 01 soft-reset register (0x3650_0000) to be written to
188               * with 0x1 (to set the nv_map bit[0] =1 (self clears))
189               * same for sgmiiphy_lane 23 soft-reset register (0x3651_0000).
190               *
191               * This will result in the rpc bits for the Lane controls to get loaded.
192               * Not happening currently.
193               *
194               * The soft_reset_sgmii occurs in the mss_ddr.c line 436, so I suppose
195               * we put the 2 new soft reset writes after that.
196               *
197               */
198             {
199                 /* sgmiiphy_lane 01 soft-reset register (0x3650_0000) */
200                 SGMIIPHY_LANE01->soft_reset = 0x000000001U;
201                 /* sgmiiphy_lane 23 soft-reset register (0x3650_0000) */
202                 SGMIIPHY_LANE23->soft_reset = 0x000000001U;
203             }
204 
205             /*
206              * Kick-off calibration, by taking calibration IP out of reset
207              */
208             /*
209              * Soft reset
210              */
211             {
212                 /* PVT soft reset - APB*/
213                 /* reg_pvt_soft_reset_periph  */
214                 CFG_DDR_SGMII_PHY->DYN_CNTL.DYN_CNTL        = (0x01U<< 10U) | (0x7FU<<0U);
215                 /* reg_pvt_soft_reset_periph  */
216                 CFG_DDR_SGMII_PHY->DYN_CNTL.DYN_CNTL        = (0x7FU<<0U);
217                 /* PVT soft reset - SCB */
218                 /* make sure out of reset */
219                 IOSCB_IO_CALIB_SGMII->SOFT_RESET_IOCALIB    = 0x1U;
220                 /* make sure out of reset */
221                 IOSCB_IO_CALIB_SGMII->SOFT_RESET_IOCALIB    = 0x0U;
222             }
223             sgmii_training_state = SGMII_WAIT_FOR_CALIB_COMPLETE;
224             break;
225 
226         case SGMII_WAIT_FOR_CALIB_COMPLETE:
227             /*
228              * Verify calibration
229              * Bank 5 PVT calibrator can be controlled by MSS firmware through APB
230              * registers to do initial calibration and re-calibration. During startup,
231              * the initial calibration can be started by default when MSS releases SGMII
232              * reset. Re-calibration is enabled by default with reg_pvt_calib_start/lock
233              * bits being set to 1 before startup, and MSS firmware can start
234              * re-calibration after startup by toggling  pvt_calib_start/lock bits per
235              * PVT calibrator spec.
236              *
237              */
238             if((CFG_DDR_SGMII_PHY->PVT_STAT.PVT_STAT & (1U << 14U)) == (1U << 14U))
239             {
240                 sgmii_training_state = SGMII_ASSERT_CALIB_LOCK;
241             }
242             break;
243 
244         case SGMII_ASSERT_CALIB_LOCK:
245             /*
246              * now assert calib lock
247              *    calibrated pcode and ncode will be written.
248              * */
249 
250             CFG_DDR_SGMII_PHY->PVT_STAT.PVT_STAT |= 0x40000000UL;
251             IOSCB_IO_CALIB_SGMII->IOC_REG0       |= (0x01U<<14U);
252             sgmii_training_state = SGMII_SET_UP_PLL;
253             break;
254 
255         case SGMII_SET_UP_PLL:
256             /*
257               * SGMii Step 3)   Wait for PLL and DLL lock
258               * Delay codes generated
259               */
260 
261             /* 0U => configure using scb, 1U => NVMAP reset */
262             sgmii_mux_config(RPC_REG_UPDATE);
263             /* 0U => configure using scb, 1U => NVMAP reset */
264             sgmii_pll_config_scb(RPC_REG_UPDATE);
265 
266             timer_out=0U;
267             sgmii_training_state = SGMII_WAIT_FOR_MSS_LOCK;
268             break;
269 
270         case SGMII_WAIT_FOR_MSS_LOCK:
271             if (CFG_DDR_SGMII_PHY->PLL_CNTL.PLL_CNTL & (1U<<7U))
272             {
273                 sgmii_training_state = SGMII_WAIT_FOR_DLL_LOCK;
274             }
275             break;
276 
277         case SGMII_WAIT_FOR_DLL_LOCK:
278             if (CFG_DDR_SGMII_PHY->RECAL_CNTL.RECAL_CNTL & (1U<<23U))
279             {
280                 sgmii_training_state = SGMII_TURN_ON_MACS;
281             }
282             break;
283 
284         case SGMII_TURN_ON_MACS:
285             /*
286              * Provide mac clocks
287              * The nw_config register for mac0 (0x2011_0004): I am forcing 'gigabit' and
288              * 'tbi' bits = 11.
289              * The same for Mac1.
290              * This starts up the tx_mac_clocks for the 2 macs.
291              *
292              */
293             /* the mac clocks need to be turned on when setting up the sgmii */
294             (void)mss_config_clk_rst(MSS_PERIPH_MAC0, (uint8_t) MPFS_HAL_FIRST_HART, PERIPHERAL_ON);
295             (void)mss_config_clk_rst(MSS_PERIPH_MAC0, (uint8_t) MPFS_HAL_FIRST_HART, PERIPHERAL_ON);
296             GEM_A_LO->network_config |= (0x01U << 10U) | (0x01U << 11U);   /* GEM0 */
297             GEM_B_LO->network_config |= (0x01U << 10U) | (0x01U << 11U);   /* GEM1 */
298             sgmii_training_state = SGMII_DETERMINE_SILICON_VARIANT;
299             break;
300 
301         case SGMII_DETERMINE_SILICON_VARIANT:
302             /*
303              * Determine Silicon variant from generated dll generated sro_dll_90_code
304              */
305             sro_dll_90_code = ((CFG_DDR_SGMII_PHY->RECAL_CNTL.RECAL_CNTL >> 16U) & 0x7FU);
306 
307             if(CFG_DDR_SGMII_PHY->SPARE_STAT.SPARE_STAT & (01U<<31U)) /* bit31 == 1 => post rev B silicon */
308             {
309                 silicon_variant = PART_REVC_OR_LATER;
310                 set_early_late_thresholds(LATE_EYE_WIDTH_PART_REVC_OR_LATER_PRE_TEST, EARLY_EYE_WIDTH_PART_REVC_OR_LATER_PRE_TEST);
311             }
312             else
313             {
314                 /*
315                  * SS  part expect  < 13
316                  * typical-typical  or FF expect  > 13
317                  */
318                 if(sro_dll_90_code < MIN_DLL_90_CODE_VALUE_INDICATING_TT_PART_REVB) /* SS part */
319                 {
320                     silicon_variant = SS_PART_REVB;
321                     set_early_late_thresholds(LATE_EYE_WIDTH_SS_PART_REVB, EARLY_EYE_WIDTH_SS_PART_REVB);
322                 }
323                 else
324                 {
325                     silicon_variant = TT_PART_REVB;
326                     set_early_late_thresholds(LATE_TT_PART_REVB, EARLY_TT_PART_REVB);
327                 }
328             }
329             sgmii_training_state = SGMII_RESET_CHANNELS;
330             break;
331 
332         case SGMII_RESET_CHANNELS:
333             /*
334              * DLL soft reset                   - Already configured
335              * PVT soft reset                   - Already configured
336              * Bank controller soft reset       - Already configured
337              * CLKMUX soft reset                - Already configured
338              * Lane0 soft reset                 - must be soft reset here
339              * Lane1 soft reset                 - must be soft reset here
340              *
341              *      __IO  uint32_t               reg_lane0_soft_reset_periph :1;  bit 13
342              *      __IO  uint32_t               reg_lane1_soft_reset_periph :1;  bit 14
343              */
344             CFG_DDR_SGMII_PHY->DYN_CNTL.DYN_CNTL  = (1U << 14U)|(1U << 13U)|(0x7FU<<0U);
345             CFG_DDR_SGMII_PHY->DYN_CNTL.DYN_CNTL  = (0U << 14U)|(0U << 13U)|(0x7FU<<0U);
346             if(silicon_variant == PART_REVC_OR_LATER)
347             {
348                 timer_out=0U;
349                 sgmii_training_state = SGMII_WAIT_10MS;
350             }
351             else
352             {
353                 sgmii_training_state = SGMII_CHANNELS_UP;
354             }
355             break;
356 
357         case SGMII_WAIT_10MS:
358             timer_out++;
359             if(timer_out >= 0xFFFU)
360             {
361                 timer_out=0U;
362                 sgmii_training_state = SGMII_CHECK_REVC_RESULT;
363             }
364             break;
365 
366         case SGMII_CHECK_REVC_RESULT:
367             if ( (CFG_DDR_SGMII_PHY->SPARE_STAT.SPARE_STAT & ARO_REF_PCODE_MASK) > ARO_REF_PCODE_REVC_THRESHOLD )
368             {
369                 /* OK, we are good */
370                 sgmii_training_state = SGMII_CHANNELS_UP;
371             }
372             else
373             {
374                 /* need to adjust eye values */
375                 set_early_late_thresholds(LATE_EYE_WIDTH_PART_REVC_OR_LATER, EARLY_EYE_WIDTH_PART_REVC_OR_LATER);
376                 /*
377                  * Now reset the channels
378                  */
379                 CFG_DDR_SGMII_PHY->DYN_CNTL.DYN_CNTL  = (1U << 14U)|(1U << 13U)|(0x7FU<<0U);
380                 CFG_DDR_SGMII_PHY->DYN_CNTL.DYN_CNTL  = (0U << 14U)|(0U << 13U)|(0x7FU<<0U);
381                 /* OK, we are good */
382                 sgmii_training_state = SGMII_CHANNELS_UP;
383             }
384             break;
385 
386         case SGMII_CHANNELS_UP:
387             /*
388              * SGMii Step 4)    Monitor the DLL codes for Voltage and Temp variation
389              * MSS E51 software sets the magnitude value of variation to flag.
390              * MSS E51 software can poll this flag.
391              * Re-calibration, if needed, is controlled by E51 software if needed.
392              * ML step 4- This is a monitoring step- to be run constantly in the back
393              * ground
394              */
395             status = SGMII_FINISHED_SETUP;
396             break;
397     } /* end of switch statement */
398 
399     return(status);
400 }
401 #endif
402 
403 /**
404  * setup_sgmii_rpc_per_config
405  * Configures SGMII RPC TIP registers
406  */
setup_sgmii_rpc_per_config(void)407 static void setup_sgmii_rpc_per_config(void)
408 {
409     CFG_DDR_SGMII_PHY->SGMII_MODE.SGMII_MODE    = (LIBERO_SETTING_SGMII_MODE & ~REG_CDR_MOVE_STEP);
410     CFG_DDR_SGMII_PHY->CH0_CNTL.CH0_CNTL        = LIBERO_SETTING_CH0_CNTL;
411     CFG_DDR_SGMII_PHY->CH1_CNTL.CH1_CNTL        = LIBERO_SETTING_CH1_CNTL;
412     CFG_DDR_SGMII_PHY->RECAL_CNTL.RECAL_CNTL    = LIBERO_SETTING_RECAL_CNTL;
413     CFG_DDR_SGMII_PHY->CLK_CNTL.CLK_CNTL        = LIBERO_SETTING_CLK_CNTL;
414     /* ibuffmx_p and _n rx1, bit 22 and 23 , rx0, bit 20 and 21 */
415     CFG_DDR_SGMII_PHY->SPARE_CNTL.SPARE_CNTL    = LIBERO_SETTING_SPARE_CNTL;
416     CFG_DDR_SGMII_PHY->PLL_CNTL.PLL_CNTL        = LIBERO_SETTING_PLL_CNTL;
417 }
418 
419 /**
420  * SGMII Off mode
421  */
sgmii_off_mode(void)422 void sgmii_off_mode(void)
423 {
424     /*
425      * do soft reset of SGMII TIP
426      */
427     CFG_DDR_SGMII_PHY->SOFT_RESET_SGMII.SOFT_RESET_SGMII = (0x01 << 8U) | 1U;
428     CFG_DDR_SGMII_PHY->SOFT_RESET_SGMII.SOFT_RESET_SGMII = 1U;
429 
430     /*
431      *
432      */
433     setup_sgmii_rpc_per_config();
434 
435     /*
436      * Resetting the SCB register only required in already in dynamic mode. If
437      * not reset, IO will not be configured.
438      */
439     IOSCB_DLL_SGMII->soft_reset = (0x01U << 0x00U);         /*  reset sgmii */
440 
441 }
442 
443 /**
444  *
445  */
ddr_pvt_calibration(void)446 void ddr_pvt_calibration(void)
447 {
448     /*
449      * R3.1
450      * PVT calibration
451      * Wait for IOEN from power detectors DDR and SGMII - IO enable signal from
452      * System Control powers on
453      *
454      * From DDR phy SAC spec:
455      *      MSS processor releases dce bus to send RPC bits to IO buffer,
456      *      setting each to it's programmed mode and then asserts
457      *      ioen high at end of this state.
458      *
459      *
460      *      Following verification required for MSS IO Calibration (DDRPHY,
461      *      SGMII and MSSIO)
462      *          Auto-calibration supply ramp time settings
463      *          Calibration in reset until ioen_bnk goes high, timer complete
464      *          and setup of bits complete
465      *              scbclk divider setting (/1)
466      *              calibration clkdiv setting
467      *              VS bit settings
468      *          Initial non-calibrated codes to IOs (functional max codes)
469      *          Calibration signal transitions
470      *              pvt_calib_status ,        r in reg     DYN_CNTL
471      *              reg_calib_reset,        w/r in reg     IOC_REG6
472      *              calib_clkdiv,           w/r in reg     IOC_REG6
473      *              soft_reset_periph_b,
474      *              calib_lock,             w/r in reg     IOC_REG0
475      *              calib_start,            w/r in reg     IOC_REG0
476      *              calib_intrpt              r in reg
477      *          Final calibration codes
478      *          Lane latching of codes
479      *          IO Glitching
480      */
481     volatile uint32_t timer_out=0U;
482 
483     #ifndef RENODE_DEBUG
484     /* sro_ioen_out  */
485     while((CFG_DDR_SGMII_PHY->IOC_REG1.IOC_REG1 & (1U<<4U)) == 0U)
486     {
487         timer_out++;
488         /*todo: add a fail break */
489     }
490     #endif
491 
492     /*
493      * R3.2  Trigger timer and wait for completion
494      * PVT calibration
495      * After IOEN is received from power detectors DDR and SGMII, extra time
496      * required for voltage to ramp.
497      * This time will come from the user- Dependent on ramp time of power supply
498      * Approximately - Bank power timer (from ioen_in to ioen_out = 10uS)?
499      *
500      */
501     /*todo: implement proper timer- user will supply ramp time */
502     timer_out=0U;
503     while(timer_out < 0xFU)
504     {
505         timer_out++;
506     }
507 
508     /*
509      * R3.2 Initiate calibration:
510      *
511      * IOC_REG6
512      *  bit 2:1 reg_calib_clkdiv
513      *  bit 0  reg_calib_reset
514      *
515      *      DDRIO:  calib_reset: 1 -> 0
516      *      mss_write(0x20007000 + 0x21C,0x00000004);
517      *      DDRIO: calib_rst_b: 0 -> 1
518      *      mss_write(0x20007000 + 0x220,0x00000000);
519      *      SGMII: calib_rst_b: 0 -> 1
520      *      mss_write(0x20007000 + 0xC1C,0x00000000);
521      *
522      */
523     /*
524      * Soft reset
525      */
526     /* PVT soft reset - APB*/
527     /* DDRIO:  calib_reset: 1 -> 0, clk divider changed - from 2 - to 3 */
528     CFG_DDR_SGMII_PHY->IOC_REG6.IOC_REG6               =    0x00000006U;
529 
530     /* PVT soft nv reset - SCB, should load from RPC */
531     IOSCB_IO_CALIB_DDR->SOFT_RESET_IOCALIB       = 0x1U; /* make sure reset */
532     IOSCB_IO_CALIB_DDR->SOFT_RESET_IOCALIB       = 0x0U; /* make sure reset */
533 
534     /*
535      * R3.4 Wait for PVT calibration to complete
536      * Check:
537      * bit 2 sro_calib_status
538      *
539      * The G5 Memory controller needs to see that the IO calibration has
540      * completed before kicking off DDR training.
541      * It uses the calib_status signal as a flag for this.
542      */
543     timer_out=0U;
544     #ifndef RENODE_DEBUG
545     {
546         /* PVT I/O - sro_calib_status -  wait for calibration to complete */
547         while((IOSCB_IO_CALIB_DDR->IOC_REG1 & 0x00000004U) == 0U)
548         {
549             timer_out++;
550         }
551         /* PVT I/O - sro_calib_status -  wait for calibration to complete */
552         while((CFG_DDR_SGMII_PHY->IOC_REG1.IOC_REG1 & 0x00000004U) == 0U)
553         {
554             timer_out++;
555         }
556     }
557     #endif
558     /*
559      * now assert calib lock
560      *
561      * */
562     {
563         CFG_DDR_SGMII_PHY->IOC_REG0.IOC_REG0    &= ~(0x01U<<14U);
564         IOSCB_IO_CALIB_DDR->IOC_REG0            &= ~(0x01U<<14U);
565         CFG_DDR_SGMII_PHY->IOC_REG0.IOC_REG0    |= (0x01U<<14U);
566         IOSCB_IO_CALIB_DDR->IOC_REG0            |= (0x01U<<14U);
567     }
568 }
569 
570 
571 /**
572  *
573  */
ddr_pvt_recalibration(void)574 void ddr_pvt_recalibration(void)
575 {
576     volatile uint32_t timer_out=0U;
577 
578     /*
579      * now assert calib start
580      *
581      * */
582     {
583         CFG_DDR_SGMII_PHY->IOC_REG0.IOC_REG0    &= ~(0x01U<<13U);
584         IOSCB_IO_CALIB_DDR->IOC_REG0            &= ~(0x01U<<13U);
585         CFG_DDR_SGMII_PHY->IOC_REG0.IOC_REG0    |= (0x01U<<13U);
586         IOSCB_IO_CALIB_DDR->IOC_REG0            |= (0x01U<<13U);
587     }
588 
589     /*
590      * R3.4 Wait for PVT calibration to complete
591      * Check:
592      * bit 2 sro_calib_status
593      *
594      * The G5 Memory controller needs to see that the IO calibration has
595      * completed before kicking off DDR training.
596      * It uses the calib_status signal as a flag for this.
597      */
598     timer_out=0U;
599     #ifndef RENODE_DEBUG
600     {
601         /* PVT I/O - sro_calib_status -  wait for calibration to complete */
602         while((IOSCB_IO_CALIB_DDR->IOC_REG1 & 0x00000004U) == 0U)
603         {
604             timer_out++;
605         }
606         /* PVT I/O - sro_calib_status -  wait for calibration to complete */
607         while((CFG_DDR_SGMII_PHY->IOC_REG1.IOC_REG1 & 0x00000004U) == 0U)
608         {
609             timer_out++;
610         }
611     }
612     #endif
613     /*
614      * now assert calib lock
615      *
616      * */
617     {
618 #if 0   /*
619          * fixme: this appears to cause wite calibration to fail, investigating
620          */
621         CFG_DDR_SGMII_PHY->IOC_REG0.IOC_REG0    &= ~(0x01U<<14U);
622         IOSCB_IO_CALIB_DDR->IOC_REG0            &= ~(0x01U<<14U);
623         CFG_DDR_SGMII_PHY->IOC_REG0.IOC_REG0    |= (0x01U<<14U);
624         IOSCB_IO_CALIB_DDR->IOC_REG0            |= (0x01U<<14U);
625 #endif
626     }
627 }
628 
629 /**
630  * Set eye thresholds
631  * @param n_late_threshold
632  * @param p_early_threshold
633  */
set_early_late_thresholds(uint8_t n_late_threshold,uint8_t p_early_threshold)634 static void set_early_late_thresholds(uint8_t n_late_threshold, uint8_t p_early_threshold)
635 {
636     uint32_t n_eye_values;
637     uint32_t p_eye_value;
638 
639     /*
640      * Set the N eye width value
641      * bits 31:29 for CH1, bits 28:26  for CH0 in spare control (N eye width value)
642      */
643     n_eye_values = (n_late_threshold << SHIFT_TO_CH0_N_EYE_VALUE);
644     n_eye_values |= (n_late_threshold << SHIFT_TO_CH1_N_EYE_VALUE);
645 
646     CFG_DDR_SGMII_PHY->SPARE_CNTL.SPARE_CNTL    = (LIBERO_SETTING_SPARE_CNTL & N_EYE_MASK) | n_eye_values;
647 
648     /*
649      * Set P values
650      */
651     p_eye_value = (p_early_threshold << SHIFT_TO_REG_RX0_EYEWIDTH);
652     CFG_DDR_SGMII_PHY->CH0_CNTL.CH0_CNTL        = ((LIBERO_SETTING_CH0_CNTL & REG_RX0_EYEWIDTH_P_MASK) | p_eye_value) | REG_RX0_EN_FLAG_N;
653     CFG_DDR_SGMII_PHY->CH1_CNTL.CH1_CNTL        = ((LIBERO_SETTING_CH1_CNTL & REG_RX0_EYEWIDTH_P_MASK) | p_eye_value) | REG_RX1_EN_FLAG_N;
654 
655 }
656 
657 #endif
658