@ -29,6 +29,18 @@
/* RTL8211x PHY Interrupt Status Register */
# define MIIM_RTL8211x_PHY_INSR 0x13
/* RTL8211F PHY Status Register */
# define MIIM_RTL8211F_PHY_STATUS 0x1a
# define MIIM_RTL8211F_AUTONEG_ENABLE 0x1000
# define MIIM_RTL8211F_PHYSTAT_SPEED 0x0030
# define MIIM_RTL8211F_PHYSTAT_GBIT 0x0020
# define MIIM_RTL8211F_PHYSTAT_100 0x0010
# define MIIM_RTL8211F_PHYSTAT_DUPLEX 0x0008
# define MIIM_RTL8211F_PHYSTAT_SPDDONE 0x0800
# define MIIM_RTL8211F_PHYSTAT_LINK 0x0004
# define MIIM_RTL8211F_PAGE_SELECT 0x1f
/* RealTek RTL8211x */
static int rtl8211x_config ( struct phy_device * phydev )
{
@ -105,6 +117,58 @@ static int rtl8211x_parse_status(struct phy_device *phydev)
return 0 ;
}
static int rtl8211f_parse_status ( struct phy_device * phydev )
{
unsigned int speed ;
unsigned int mii_reg ;
int i = 0 ;
phy_write ( phydev , MDIO_DEVAD_NONE , MIIM_RTL8211F_PAGE_SELECT , 0xa43 ) ;
mii_reg = phy_read ( phydev , MDIO_DEVAD_NONE , MIIM_RTL8211F_PHY_STATUS ) ;
phydev - > link = 1 ;
while ( ! ( mii_reg & MIIM_RTL8211F_PHYSTAT_LINK ) ) {
if ( i > PHY_AUTONEGOTIATE_TIMEOUT ) {
puts ( " TIMEOUT ! \n " ) ;
phydev - > link = 0 ;
break ;
}
if ( ( i + + % 1000 ) = = 0 )
putc ( ' . ' ) ;
udelay ( 1000 ) ;
mii_reg = phy_read ( phydev , MDIO_DEVAD_NONE ,
MIIM_RTL8211F_PHY_STATUS ) ;
}
if ( mii_reg & MIIM_RTL8211F_PHYSTAT_DUPLEX )
phydev - > duplex = DUPLEX_FULL ;
else
phydev - > duplex = DUPLEX_HALF ;
speed = ( mii_reg & MIIM_RTL8211F_PHYSTAT_SPEED ) ;
switch ( speed ) {
case MIIM_RTL8211F_PHYSTAT_GBIT :
phydev - > speed = SPEED_1000 ;
break ;
case MIIM_RTL8211F_PHYSTAT_100 :
phydev - > speed = SPEED_100 ;
break ;
default :
phydev - > speed = SPEED_10 ;
}
if ( phydev - > interface = = PHY_INTERFACE_MODE_RGMII ) {
/* enable TXDLY */
phy_write ( phydev , MDIO_DEVAD_NONE ,
MIIM_RTL8211F_PAGE_SELECT , 0xd08 ) ;
phy_write ( phydev , MDIO_DEVAD_NONE , 0x11 , 0x109 ) ;
}
return 0 ;
}
static int rtl8211x_startup ( struct phy_device * phydev )
{
/* Read the Status (2x to make sure link is right) */
@ -114,6 +178,15 @@ static int rtl8211x_startup(struct phy_device *phydev)
return 0 ;
}
static int rtl8211f_startup ( struct phy_device * phydev )
{
/* Read the Status (2x to make sure link is right) */
genphy_update_link ( phydev ) ;
rtl8211f_parse_status ( phydev ) ;
return 0 ;
}
/* Support for RTL8211B PHY */
static struct phy_driver RTL8211B_driver = {
. name = " RealTek RTL8211B " ,
@ -147,10 +220,22 @@ static struct phy_driver RTL8211DN_driver = {
. shutdown = & genphy_shutdown ,
} ;
/* Support for RTL8211F PHY */
static struct phy_driver RTL8211F_driver = {
. name = " RealTek RTL8211F " ,
. uid = 0x1cc916 ,
. mask = 0xffffff ,
. features = PHY_GBIT_FEATURES ,
. config = & rtl8211x_config ,
. startup = & rtl8211f_startup ,
. shutdown = & genphy_shutdown ,
} ;
int phy_realtek_init ( void )
{
phy_register ( & RTL8211B_driver ) ;
phy_register ( & RTL8211E_driver ) ;
phy_register ( & RTL8211F_driver ) ;
phy_register ( & RTL8211DN_driver ) ;
return 0 ;