@ -147,12 +147,43 @@ int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
return - ENODEV ;
}
# define BC3_SHIFT 9
# define DC3_SHIFT 6
# define FC3_SHIFT 0
# define BC2_SHIFT 19
# define DC2_SHIFT 16
# define FC2_SHIFT 10
# define BC1_SHIFT 29
# define DC1_SHIFT 26
# define FC1_SHIFT 20
# define BC_MASK 0x1
# define DC_MASK 0x7
# define FC_MASK 0x3F
# define FUSE_VAL_MASK 0x00000003
# define FUSE_VAL_SHIFT 30
# define CR0_DCBIAS_SHIFT 5
# define CR1_FCAP_SHIFT 15
# define CR1_BCAP_SHIFT 29
# define FCAP_MASK 0x001F8000
# define BCAP_MASK 0x20000000
# define BCAP_OVD_MASK 0x10000000
# define BYP_CAL_MASK 0x02000000
u64 serdes_init ( u32 sd , u32 sd_addr , u32 sd_prctl_mask , u32 sd_prctl_shift )
{
ccsr_gur_t * gur = ( void __iomem * ) ( CONFIG_SYS_MPC85xx_GUTS_ADDR ) ;
u64 serdes_prtcl_map = 0 ;
u32 cfg ;
int lane ;
# ifdef CONFIG_SYS_FSL_ERRATUM_A007186
struct ccsr_sfp_regs __iomem * sfp_regs =
( struct ccsr_sfp_regs __iomem * ) ( CONFIG_SYS_SFP_ADDR ) ;
u32 pll_num , pll_status , bc , dc , fc , pll_cr_upd , pll_cr0 , pll_cr1 ;
u32 bc_status , fc_status , dc_status , pll_sr2 ;
serdes_corenet_t __iomem * srds_regs = ( void * ) sd_addr ;
u32 sfp_spfr0 , sel ;
# endif
cfg = in_be32 ( & gur - > rcwsr [ 4 ] ) & sd_prctl_mask ;
/* Is serdes enabled at all? */
@ -161,6 +192,123 @@ u64 serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift)
return 0 ;
}
/* Erratum A-007186
* Freescale Scratch Pad Fuse Register n ( SFP_FSPFR0 )
* The workaround requires factory pre - set SerDes calibration values to be
* read from a fuse block ( Freescale Scratch Pad Fuse Register SFP_FSPFR0 )
* These values have been shown to work across the
* entire temperature range for all SerDes . These values are then written into
* the SerDes registers to calibrate the SerDes PLL .
*
* This workaround for the protocols and rates that only have the Ring VCO .
*/
# ifdef CONFIG_SYS_FSL_ERRATUM_A007186
sfp_spfr0 = in_be32 ( & sfp_regs - > fsl_spfr0 ) ;
debug ( " A007186: sfp_spfr0= %x \n " , sfp_spfr0 ) ;
sel = ( sfp_spfr0 > > FUSE_VAL_SHIFT ) & FUSE_VAL_MASK ;
if ( sel = = 0x01 | | sel = = 0x02 ) {
for ( pll_num = 0 ; pll_num < SRDS_MAX_BANK ; pll_num + + ) {
pll_status = in_be32 ( & srds_regs - > bank [ pll_num ] . pllcr0 ) ;
debug ( " A007186: pll_num=%x pllcr0=%x \n " ,
pll_num , pll_status ) ;
/* STEP 1 */
/* Read factory pre-set SerDes calibration values
* from fuse block ( SFP scratch register - sfp_spfr0 )
*/
switch ( pll_status & SRDS_PLLCR0_FRATE_SEL_MASK ) {
case SRDS_PLLCR0_FRATE_SEL_3_0 :
case SRDS_PLLCR0_FRATE_SEL_3_072 :
debug ( " A007186: 3.0/3.072 protocol rate \n " ) ;
bc = ( sfp_spfr0 > > BC1_SHIFT ) & BC_MASK ;
dc = ( sfp_spfr0 > > DC1_SHIFT ) & DC_MASK ;
fc = ( sfp_spfr0 > > FC1_SHIFT ) & FC_MASK ;
break ;
case SRDS_PLLCR0_FRATE_SEL_3_125 :
debug ( " A007186: 3.125 protocol rate \n " ) ;
bc = ( sfp_spfr0 > > BC2_SHIFT ) & BC_MASK ;
dc = ( sfp_spfr0 > > DC2_SHIFT ) & DC_MASK ;
fc = ( sfp_spfr0 > > FC2_SHIFT ) & FC_MASK ;
break ;
case SRDS_PLLCR0_FRATE_SEL_3_75 :
debug ( " A007186: 3.75 protocol rate \n " ) ;
bc = ( sfp_spfr0 > > BC1_SHIFT ) & BC_MASK ;
dc = ( sfp_spfr0 > > DC1_SHIFT ) & DC_MASK ;
fc = ( sfp_spfr0 > > FC1_SHIFT ) & FC_MASK ;
break ;
default :
continue ;
}
/* STEP 2 */
/* Write SRDSxPLLnCR1[11:16] = FC
* Write SRDSxPLLnCR1 [ 2 ] = BC
*/
pll_cr1 = in_be32 ( & srds_regs - > bank [ pll_num ] . pllcr1 ) ;
pll_cr_upd = ( ( ( bc < < CR1_BCAP_SHIFT ) & BCAP_MASK ) |
( ( fc < < CR1_FCAP_SHIFT ) & FCAP_MASK ) ) ;
out_be32 ( & srds_regs - > bank [ pll_num ] . pllcr1 ,
( pll_cr_upd | pll_cr1 ) ) ;
debug ( " A007186: pll_num=%x Updated PLLCR1=%x \n " ,
pll_num , ( pll_cr_upd | pll_cr1 ) ) ;
/* Write SRDSxPLLnCR0[24:26] = DC
*/
pll_cr0 = in_be32 ( & srds_regs - > bank [ pll_num ] . pllcr0 ) ;
out_be32 ( & srds_regs - > bank [ pll_num ] . pllcr0 ,
pll_cr0 | ( dc < < CR0_DCBIAS_SHIFT ) ) ;
debug ( " A007186: pll_num=%x, Updated PLLCR0=%x \n " ,
pll_num , ( pll_cr0 | ( dc < < CR0_DCBIAS_SHIFT ) ) ) ;
/* Write SRDSxPLLnCR1[3] = 1
* Write SRDSxPLLnCR1 [ 6 ] = 1
*/
pll_cr1 = in_be32 ( & srds_regs - > bank [ pll_num ] . pllcr1 ) ;
pll_cr_upd = ( BCAP_OVD_MASK | BYP_CAL_MASK ) ;
out_be32 ( & srds_regs - > bank [ pll_num ] . pllcr1 ,
( pll_cr_upd | pll_cr1 ) ) ;
debug ( " A007186: pll_num=%x Updated PLLCR1=%x \n " ,
pll_num , ( pll_cr_upd | pll_cr1 ) ) ;
/* STEP 3 */
/* Read the status Registers */
/* Verify SRDSxPLLnSR2[8] = BC */
pll_sr2 = in_be32 ( & srds_regs - > bank [ pll_num ] . pllsr2 ) ;
debug ( " A007186: pll_num=%x pllsr2=%x \n " ,
pll_num , pll_sr2 ) ;
bc_status = ( pll_sr2 > > 23 ) & BC_MASK ;
if ( bc_status ! = bc )
debug ( " BC mismatch \n " ) ;
fc_status = ( pll_sr2 > > 16 ) & FC_MASK ;
if ( fc_status ! = fc )
debug ( " FC mismatch \n " ) ;
pll_cr0 = in_be32 ( & srds_regs - > bank [ pll_num ] . pllcr0 ) ;
out_be32 ( & srds_regs - > bank [ pll_num ] . pllcr0 , pll_cr0 |
0x02000000 ) ;
pll_sr2 = in_be32 ( & srds_regs - > bank [ pll_num ] . pllsr2 ) ;
dc_status = ( pll_sr2 > > 17 ) & DC_MASK ;
if ( dc_status ! = dc )
debug ( " DC mismatch \n " ) ;
pll_cr0 = in_be32 ( & srds_regs - > bank [ pll_num ] . pllcr0 ) ;
out_be32 ( & srds_regs - > bank [ pll_num ] . pllcr0 , pll_cr0 &
0xfdffffff ) ;
/* STEP 4 */
/* Wait 750us to verify the PLL is locked
* by checking SRDSxPLLnCR0 [ 8 ] = 1.
*/
udelay ( 750 ) ;
pll_status = in_be32 ( & srds_regs - > bank [ pll_num ] . pllcr0 ) ;
debug ( " A007186: pll_num=%x pllcr0=%x \n " ,
pll_num , pll_status ) ;
if ( ( pll_status & SRDS_PLLCR0_PLL_LCK ) = = 0 )
printf ( " A007186 Serdes PLL not locked \n " ) ;
else
debug ( " A007186 Serdes PLL locked \n " ) ;
}
}
# endif
cfg > > = sd_prctl_shift ;
printf ( " Using SERDES%d Protocol: %d (0x%x) \n " , sd + 1 , cfg , cfg ) ;
if ( ! is_serdes_prtcl_valid ( sd , cfg ) )