@ -22,6 +22,7 @@
# include <asm/fsl_law.h>
# include <asm/fsl_serdes.h>
# include <asm/fsl_srio.h>
# include <asm/errno.h>
# define SRIO_PORT_ACCEPT_ALL 0x10000001
# define SRIO_IB_ATMU_AR 0x80f55000
@ -52,6 +53,185 @@
# error "No defines for DEVDISR_SRIO"
# endif
# ifdef CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
/*
* Erratum A - 004034
* Affects : SRIO
* Description : During port initialization , the SRIO port performs
* lane synchronization ( detecting valid symbols on a lane ) and
* lane alignment ( coordinating multiple lanes to receive valid data
* across lanes ) . Internal errors in lane synchronization and lane
* alignment may cause failure to achieve link initialization at
* the configured port width .
* An SRIO port configured as a 4 x port may see one of these scenarios :
* 1. One or more lanes fails to achieve lane synchronization . Depending
* on which lanes fail , this may result in downtraining from 4 x to 1 x
* on lane 0 , 4 x to 1 x on lane R ( redundant lane ) .
* 2. The link may fail to achieve lane alignment as a 4 x , even though
* all 4 lanes achieve lane synchronization , and downtrain to a 1 x .
* An SRIO port configured as a 1 x port may fail to complete port
* initialization ( PnESCSR [ PU ] never deasserts ) because of scenario 1.
* Impact : SRIO port may downtrain to 1 x , or may fail to complete
* link initialization . Once a port completes link initialization
* successfully , it will operate normally .
*/
static int srio_erratum_a004034 ( u8 port )
{
serdes_corenet_t * srds_regs ;
u32 conf_lane ;
u32 init_lane ;
int idx , first , last ;
u32 i ;
unsigned long long end_tick ;
struct ccsr_rio * srio_regs = ( void * ) CONFIG_SYS_FSL_SRIO_ADDR ;
srds_regs = ( void * ) ( CONFIG_SYS_FSL_CORENET_SERDES_ADDR ) ;
conf_lane = ( in_be32 ( ( void * ) & srds_regs - > srdspccr0 )
> > ( 12 - port * 4 ) ) & 0x3 ;
init_lane = ( in_be32 ( ( void * ) & srio_regs - > lp_serial
. port [ port ] . pccsr ) > > 27 ) & 0x7 ;
/*
* Start a counter set to ~ 2 ms after the SERDES reset is
* complete ( SERDES SRDSBnRSTCTL [ RST_DONE ] = 1 for n
* corresponding to the SERDES bank / PLL for the SRIO port ) .
*/
if ( in_be32 ( ( void * ) & srds_regs - > bank [ 0 ] . rstctl )
& SRDS_RSTCTL_RSTDONE ) {
/*
* Poll the port uninitialized status ( SRIO PnESCSR [ PO ] ) until
* PO = 1 or the counter expires . If the counter expires , the
* port has failed initialization : go to recover steps . If PO = 1
* and the desired port width is 1 x , go to normal steps . If
* PO = 1 and the desired port width is 4 x , go to recover steps .
*/
end_tick = usec2ticks ( 2000 ) + get_ticks ( ) ;
do {
if ( in_be32 ( ( void * ) & srio_regs - > lp_serial
. port [ port ] . pescsr ) & 0x2 ) {
if ( conf_lane = = 0x1 )
goto host_ok ;
else {
if ( init_lane = = 0x2 )
goto host_ok ;
else
break ;
}
}
} while ( end_tick > get_ticks ( ) ) ;
/* recover at most 3 times */
for ( i = 0 ; i < 3 ; i + + ) {
/* Set SRIO PnCCSR[PD]=1 */
setbits_be32 ( ( void * ) & srio_regs - > lp_serial
. port [ port ] . pccsr ,
0x800000 ) ;
/*
* Set SRIO PnPCR [ OBDEN ] on the host to
* enable the discarding of any pending packets .
*/
setbits_be32 ( ( void * ) & srio_regs - > impl . port [ port ] . pcr ,
0x04 ) ;
/* Wait 50 us */
udelay ( 50 ) ;
/* Run sync command */
isync ( ) ;
if ( port )
first = serdes_get_first_lane ( SRIO2 ) ;
else
first = serdes_get_first_lane ( SRIO1 ) ;
if ( unlikely ( first < 0 ) )
return - ENODEV ;
if ( conf_lane = = 0x1 )
last = first ;
else
last = first + 3 ;
/*
* Set SERDES BnGCRm0 [ RRST ] = 0 for each SRIO
* bank n and lane m .
*/
for ( idx = first ; idx < = last ; idx + + )
clrbits_be32 ( & srds_regs - > lane [ idx ] . gcr0 ,
SRDS_GCR0_RRST ) ;
/*
* Read SERDES BnGCRm0 for each SRIO
* bank n and lane m
*/
for ( idx = first ; idx < = last ; idx + + )
in_be32 ( & srds_regs - > lane [ idx ] . gcr0 ) ;
/* Run sync command */
isync ( ) ;
/* Wait >= 100 ns */
udelay ( 1 ) ;
/*
* Set SERDES BnGCRm0 [ RRST ] = 1 for each SRIO
* bank n and lane m .
*/
for ( idx = first ; idx < = last ; idx + + )
setbits_be32 ( & srds_regs - > lane [ idx ] . gcr0 ,
SRDS_GCR0_RRST ) ;
/*
* Read SERDES BnGCRm0 for each SRIO
* bank n and lane m
*/
for ( idx = first ; idx < = last ; idx + + )
in_be32 ( & srds_regs - > lane [ idx ] . gcr0 ) ;
/* Run sync command */
isync ( ) ;
/* Wait >= 300 ns */
udelay ( 1 ) ;
/* Write 1 to clear all bits in SRIO PnSLCSR */
out_be32 ( ( void * ) & srio_regs - > impl . port [ port ] . slcsr ,
0xffffffff ) ;
/* Clear SRIO PnPCR[OBDEN] on the host */
clrbits_be32 ( ( void * ) & srio_regs - > impl . port [ port ] . pcr ,
0x04 ) ;
/* Set SRIO PnCCSR[PD]=0 */
clrbits_be32 ( ( void * ) & srio_regs - > lp_serial
. port [ port ] . pccsr ,
0x800000 ) ;
/* Wait >= 24 ms */
udelay ( 24000 ) ;
/* Poll the state of the port again */
init_lane =
( in_be32 ( ( void * ) & srio_regs - > lp_serial
. port [ port ] . pccsr ) > > 27 ) & 0x7 ;
if ( in_be32 ( ( void * ) & srio_regs - > lp_serial
. port [ port ] . pescsr ) & 0x2 ) {
if ( conf_lane = = 0x1 )
goto host_ok ;
else {
if ( init_lane = = 0x2 )
goto host_ok ;
}
}
if ( i = = 2 )
return - ENODEV ;
}
} else
return - ENODEV ;
host_ok :
/* Poll PnESCSR[OES] on the host until it is clear */
end_tick = usec2ticks ( 1000000 ) + get_ticks ( ) ;
do {
if ( ! ( in_be32 ( ( void * ) & srio_regs - > lp_serial . port [ port ] . pescsr )
& 0x10000 ) ) {
out_be32 ( ( ( void * ) & srio_regs - > lp_serial
. port [ port ] . pescsr ) , 0xffffffff ) ;
out_be32 ( ( ( void * ) & srio_regs - > phys_err
. port [ port ] . edcsr ) , 0 ) ;
out_be32 ( ( ( void * ) & srio_regs - > logical_err . ltledcsr ) , 0 ) ;
return 0 ;
}
} while ( end_tick > get_ticks ( ) ) ;
return - ENODEV ;
}
# endif
void srio_init ( void )
{
ccsr_gur_t * gur = ( void * ) CONFIG_SYS_MPC8xxx_GUTS_ADDR ;
@ -62,6 +242,11 @@ void srio_init(void)
law_size_bits ( CONFIG_SYS_SRIO1_MEM_SIZE ) ,
LAW_TRGT_IF_RIO_1 ) ;
srio1_used = 1 ;
# ifdef CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
if ( srio_erratum_a004034 ( 0 ) < 0 )
printf ( " SRIO1: enabled but port error \n " ) ;
else
# endif
printf ( " SRIO1: enabled \n " ) ;
} else {
printf ( " SRIO1: disabled \n " ) ;
@ -73,7 +258,13 @@ void srio_init(void)
law_size_bits ( CONFIG_SYS_SRIO2_MEM_SIZE ) ,
LAW_TRGT_IF_RIO_2 ) ;
srio2_used = 1 ;
# ifdef CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
if ( srio_erratum_a004034 ( 1 ) < 0 )
printf ( " SRIO2: enabled but port error \n " ) ;
else
# endif
printf ( " SRIO2: enabled \n " ) ;
} else {
printf ( " SRIO2: disabled \n " ) ;
}