@ -20,6 +20,9 @@
* author Andy Fleming
*
*/
# include <config.h>
# include <common.h>
# include <micrel.h>
# include <phy.h>
static struct phy_driver KSZ804_driver = {
@ -42,10 +45,94 @@ static struct phy_driver KS8721_driver = {
. shutdown = & genphy_shutdown ,
} ;
/* ksz9021 PHY Registers */
# define MII_KSZ9021_EXTENDED_CTRL 0x0b
# define MII_KSZ9021_EXTENDED_DATAW 0x0c
# define MII_KSZ9021_EXTENDED_DATAR 0x0d
# define MII_KSZ9021_PHY_CTL 0x1f
# define MIIM_KSZ9021_PHYCTL_1000 (1 << 6)
# define MIIM_KSZ9021_PHYCTL_100 (1 << 5)
# define MIIM_KSZ9021_PHYCTL_10 (1 << 4)
# define MIIM_KSZ9021_PHYCTL_DUPLEX (1 << 3)
# define CTRL1000_PREFER_MASTER (1 << 10)
# define CTRL1000_CONFIG_MASTER (1 << 11)
# define CTRL1000_MANUAL_CONFIG (1 << 12)
int ksz9021_phy_extended_write ( struct phy_device * phydev , int regnum , u16 val )
{
/* extended registers */
phy_write ( phydev , MDIO_DEVAD_NONE ,
MII_KSZ9021_EXTENDED_CTRL , regnum | 0x8000 ) ;
return phy_write ( phydev , MDIO_DEVAD_NONE ,
MII_KSZ9021_EXTENDED_DATAW , val ) ;
}
int ksz9021_phy_extended_read ( struct phy_device * phydev , int regnum )
{
/* extended registers */
phy_write ( phydev , MDIO_DEVAD_NONE , MII_KSZ9021_EXTENDED_CTRL , regnum ) ;
return phy_read ( phydev , MDIO_DEVAD_NONE , MII_KSZ9021_EXTENDED_DATAR ) ;
}
/* Micrel ksz9021 */
static int ksz9021_config ( struct phy_device * phydev )
{
unsigned ctrl1000 = 0 ;
const unsigned master = CTRL1000_PREFER_MASTER |
CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG ;
unsigned features = phydev - > drv - > features ;
if ( getenv ( " disable_giga " ) )
features & = ~ ( SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full ) ;
/* force master mode for 1000BaseT due to chip errata */
if ( features & SUPPORTED_1000baseT_Half )
ctrl1000 | = ADVERTISE_1000HALF | master ;
if ( features & SUPPORTED_1000baseT_Full )
ctrl1000 | = ADVERTISE_1000FULL | master ;
phydev - > advertising = phydev - > supported = features ;
phy_write ( phydev , MDIO_DEVAD_NONE , MII_CTRL1000 , ctrl1000 ) ;
genphy_config_aneg ( phydev ) ;
genphy_restart_aneg ( phydev ) ;
return 0 ;
}
static int ksz9021_startup ( struct phy_device * phydev )
{
unsigned phy_ctl ;
genphy_update_link ( phydev ) ;
phy_ctl = phy_read ( phydev , MDIO_DEVAD_NONE , MII_KSZ9021_PHY_CTL ) ;
if ( phy_ctl & MIIM_KSZ9021_PHYCTL_DUPLEX )
phydev - > duplex = DUPLEX_FULL ;
else
phydev - > duplex = DUPLEX_HALF ;
if ( phy_ctl & MIIM_KSZ9021_PHYCTL_1000 )
phydev - > speed = SPEED_1000 ;
else if ( phy_ctl & MIIM_KSZ9021_PHYCTL_100 )
phydev - > speed = SPEED_100 ;
else if ( phy_ctl & MIIM_KSZ9021_PHYCTL_10 )
phydev - > speed = SPEED_10 ;
return 0 ;
}
static struct phy_driver ksz9021_driver = {
. name = " Micrel ksz9021 " ,
. uid = 0x221610 ,
. mask = 0xfffff0 ,
. features = PHY_GBIT_FEATURES ,
. config = & ksz9021_config ,
. startup = & ksz9021_startup ,
. shutdown = & genphy_shutdown ,
} ;
int phy_micrel_init ( void )
{
phy_register ( & KSZ804_driver ) ;
phy_register ( & KS8721_driver ) ;
phy_register ( & ksz9021_driver ) ;
return 0 ;
}