@ -99,7 +99,6 @@ unsigned int mclink_fpgacount;
struct ihs_fpga * fpga_ptr [ ] = CONFIG_SYS_FPGA_PTR ;
static int setup_88e1518 ( const char * bus , unsigned char addr ) ;
static int verify_88e1518 ( const char * bus , unsigned char addr ) ;
int fpga_set_reg ( u32 fpga , u16 * reg , off_t regoff , u16 data )
{
@ -405,11 +404,7 @@ int last_stage_init(void)
if ( ( mux_ch = = 1 ) & & ! ch0_rgmii2_present )
continue ;
if ( ! verify_88e1518 ( bb_miiphy_buses [ 0 ] . name , mux_ch ) ) {
printf ( " Fixup 88e1518 erratum on %s phy %u \n " ,
bb_miiphy_buses [ 0 ] . name , mux_ch ) ;
setup_88e1518 ( bb_miiphy_buses [ 0 ] . name , mux_ch ) ;
}
setup_88e1518 ( bb_miiphy_buses [ 0 ] . name , mux_ch ) ;
}
}
@ -434,11 +429,7 @@ int last_stage_init(void)
if ( feature_carrier_speed = = CARRIER_SPEED_1G ) {
miiphy_register ( bb_miiphy_buses [ k ] . name ,
bb_miiphy_read , bb_miiphy_write ) ;
if ( ! verify_88e1518 ( bb_miiphy_buses [ k ] . name , 0 ) ) {
printf ( " Fixup 88e1518 erratum on %s \n " ,
bb_miiphy_buses [ k ] . name ) ;
setup_88e1518 ( bb_miiphy_buses [ k ] . name , 0 ) ;
}
setup_88e1518 ( bb_miiphy_buses [ k ] . name , 0 ) ;
}
}
@ -652,56 +643,189 @@ struct bb_miiphy_bus bb_miiphy_buses[] = {
int bb_miiphy_buses_num = sizeof ( bb_miiphy_buses ) /
sizeof ( bb_miiphy_buses [ 0 ] ) ;
enum {
MIICMD_SET ,
MIICMD_MODIFY ,
MIICMD_VERIFY_VALUE ,
MIICMD_WAIT_FOR_VALUE ,
} ;
struct mii_setupcmd {
u8 token ;
u8 reg ;
u16 data ;
u16 mask ;
u32 timeout ;
} ;
/*
* Workaround for erratum mentioned in 88E1518 release notes
* verify we are talking to a 88e1518
*/
struct mii_setupcmd verify_88e1518 [ ] = {
{ MIICMD_SET , 22 , 0x0000 } ,
{ MIICMD_VERIFY_VALUE , 2 , 0x0141 , 0xffff } ,
{ MIICMD_VERIFY_VALUE , 3 , 0x0dd0 , 0xfff0 } ,
} ;
static int verify_88e1518 ( const char * bus , unsigned char addr )
{
u16 phy_id1 , phy_id2 ;
if ( miiphy_read ( bus , addr , 2 , & phy_id1 ) | |
miiphy_read ( bus , addr , 3 , & phy_id2 ) ) {
printf ( " Error reading from the PHY addr=%02x \n " , addr ) ;
return - EIO ;
}
/*
* workaround for erratum mentioned in 88E1518 release notes
*/
struct mii_setupcmd fixup_88e1518 [ ] = {
{ MIICMD_SET , 22 , 0x00ff } ,
{ MIICMD_SET , 17 , 0x214b } ,
{ MIICMD_SET , 16 , 0x2144 } ,
{ MIICMD_SET , 17 , 0x0c28 } ,
{ MIICMD_SET , 16 , 0x2146 } ,
{ MIICMD_SET , 17 , 0xb233 } ,
{ MIICMD_SET , 16 , 0x214d } ,
{ MIICMD_SET , 17 , 0xcc0c } ,
{ MIICMD_SET , 16 , 0x2159 } ,
{ MIICMD_SET , 22 , 0x00fb } ,
{ MIICMD_SET , 7 , 0xc00d } ,
{ MIICMD_SET , 22 , 0x0000 } ,
} ;
if ( ( phy_id1 ! = 0x0141 ) | | ( ( phy_id2 & 0xfff0 ) ! = 0x0dd0 ) )
return - EINVAL ;
/*
* default initialization :
* - set RGMII receive timing to " receive clock transition when data stable "
* - set RGMII transmit timing to " transmit clock internally delayed "
* - set RGMII output impedance target to 78 , 8 Ohm
* - run output impedance calibration
* - set autonegotiation advertise to 1000F D only
*/
struct mii_setupcmd default_88e1518 [ ] = {
{ MIICMD_SET , 22 , 0x0002 } ,
{ MIICMD_MODIFY , 21 , 0x0030 , 0x0030 } ,
{ MIICMD_MODIFY , 25 , 0x0000 , 0x0003 } ,
{ MIICMD_MODIFY , 24 , 0x8000 , 0x8000 } ,
{ MIICMD_WAIT_FOR_VALUE , 24 , 0x4000 , 0x4000 , 2000 } ,
{ MIICMD_SET , 22 , 0x0000 } ,
{ MIICMD_MODIFY , 4 , 0x0000 , 0x01e0 } ,
{ MIICMD_MODIFY , 9 , 0x0200 , 0x0300 } ,
} ;
return 0 ;
}
/*
* turn off CLK125 for PHY daughterboard
*/
struct mii_setupcmd ch1fix_88e1518 [ ] = {
{ MIICMD_SET , 22 , 0x0002 } ,
{ MIICMD_MODIFY , 16 , 0x0006 , 0x0006 } ,
{ MIICMD_SET , 22 , 0x0000 } ,
} ;
struct regfix_88e1518 {
u8 reg ;
u16 data ;
} regfix_88e1518 [ ] = {
{ 22 , 0x00ff } ,
{ 17 , 0x214b } ,
{ 16 , 0x2144 } ,
{ 17 , 0x0c28 } ,
{ 16 , 0x2146 } ,
{ 17 , 0xb233 } ,
{ 16 , 0x214d } ,
{ 17 , 0xcc0c } ,
{ 16 , 0x2159 } ,
{ 22 , 0x00fb } ,
{ 7 , 0xc00d } ,
{ 22 , 0x0000 } ,
/*
* perform copper software reset
*/
struct mii_setupcmd swreset_88e1518 [ ] = {
{ MIICMD_SET , 22 , 0x0000 } ,
{ MIICMD_MODIFY , 0 , 0x8000 , 0x8000 } ,
{ MIICMD_WAIT_FOR_VALUE , 0 , 0x0000 , 0x8000 , 2000 } ,
} ;
static int setup_88e1518 ( const char * bus , unsigned char addr )
static int process_setupcmd ( const char * bus , unsigned char addr ,
struct mii_setupcmd * setupcmd )
{
int res ;
u8 reg = setupcmd - > reg ;
u16 data = setupcmd - > data ;
u16 mask = setupcmd - > mask ;
u32 timeout = setupcmd - > timeout ;
u16 orig_data ;
unsigned long start ;
debug ( " mii %s:%u reg %2u " , bus , addr , reg ) ;
switch ( setupcmd - > token ) {
case MIICMD_MODIFY :
res = miiphy_read ( bus , addr , reg , & orig_data ) ;
if ( res )
break ;
debug ( " is %04x. (value %04x mask %04x) " , orig_data , data ,
mask ) ;
data = ( orig_data & ~ mask ) | ( data & mask ) ;
case MIICMD_SET :
debug ( " => %04x \n " , data ) ;
res = miiphy_write ( bus , addr , reg , data ) ;
break ;
case MIICMD_VERIFY_VALUE :
res = miiphy_read ( bus , addr , reg , & orig_data ) ;
if ( res )
break ;
if ( ( orig_data & mask ) ! = ( data & mask ) )
res = - 1 ;
debug ( " (value %04x mask %04x) == %04x? %s \n " , data , mask ,
orig_data , res ? " FAIL " : " PASS " ) ;
break ;
case MIICMD_WAIT_FOR_VALUE :
res = - 1 ;
start = get_timer ( 0 ) ;
while ( ( res ! = 0 ) & & ( get_timer ( start ) < timeout ) ) {
res = miiphy_read ( bus , addr , reg , & orig_data ) ;
if ( res )
continue ;
if ( ( orig_data & mask ) ! = ( data & mask ) )
res = - 1 ;
}
debug ( " (value %04x mask %04x) == %04x? %s after %lu ms \n " , data ,
mask , orig_data , res ? " FAIL " : " PASS " ,
get_timer ( start ) ) ;
break ;
default :
res = - 1 ;
break ;
}
return res ;
}
static int process_setup ( const char * bus , unsigned char addr ,
struct mii_setupcmd * setupcmd , unsigned int count )
{
int res = 0 ;
unsigned int k ;
for ( k = 0 ; k < ARRAY_SIZE ( regfix_88e1518 ) ; + + k ) {
if ( miiphy_write ( bus , addr ,
regfix_88e1518 [ k ] . reg ,
regfix_88e1518 [ k ] . data ) ) {
printf ( " Error writing to the PHY addr=%02x \n " , addr ) ;
return - 1 ;
for ( k = 0 ; k < count ; + + k ) {
res = process_setupcmd ( bus , addr , & setupcmd [ k ] ) ;
if ( res ) {
printf ( " mii cmd %u on bus %s addr %u failed, aborting setup " ,
setupcmd [ k ] . token , bus , addr ) ;
break ;
}
}
return res ;
}
static int setup_88e1518 ( const char * bus , unsigned char addr )
{
int res ;
res = process_setup ( bus , addr ,
verify_88e1518 , ARRAY_SIZE ( verify_88e1518 ) ) ;
if ( res )
return res ;
res = process_setup ( bus , addr ,
fixup_88e1518 , ARRAY_SIZE ( fixup_88e1518 ) ) ;
if ( res )
return res ;
res = process_setup ( bus , addr ,
default_88e1518 , ARRAY_SIZE ( default_88e1518 ) ) ;
if ( res )
return res ;
if ( addr ) {
res = process_setup ( bus , addr ,
ch1fix_88e1518 , ARRAY_SIZE ( ch1fix_88e1518 ) ) ;
if ( res )
return res ;
}
res = process_setup ( bus , addr ,
swreset_88e1518 , ARRAY_SIZE ( swreset_88e1518 ) ) ;
if ( res )
return res ;
return 0 ;
}