diff options
Diffstat (limited to 'drivers/net/phy')
-rw-r--r-- | drivers/net/phy/teranetics.c | 16 | ||||
-rw-r--r-- | drivers/net/phy/vitesse.c | 67 |
2 files changed, 81 insertions, 2 deletions
diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c index 78447b7..84ce736 100644 --- a/drivers/net/phy/teranetics.c +++ b/drivers/net/phy/teranetics.c @@ -34,9 +34,21 @@ int tn2020_config(struct phy_device *phydev) unsigned short restart_an = (MDIO_AN_CTRL1_RESTART | MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_XNP); + u8 phy_hwversion; - phy_write(phydev, 30, 93, 2); - phy_write(phydev, MDIO_MMD_AN, MDIO_CTRL1, restart_an); + /* + * bit 15:12 of register 30.32 indicates PHY hardware + * version. It can be used to distinguish TN80xx from + * TN2020. TN2020 needs write 0x2 to 30.93, but TN80xx + * needs 0x1. + */ + phy_hwversion = (phy_read(phydev, 30, 32) >> 12) & 0xf; + if (phy_hwversion <= 3) { + phy_write(phydev, 30, 93, 2); + phy_write(phydev, MDIO_MMD_AN, MDIO_CTRL1, restart_an); + } else { + phy_write(phydev, 30, 93, 1); + } } return 0; diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index 6c5cb99..c283d82 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -48,6 +48,19 @@ #define MIIM_VSC8601_SKEW_CTRL 0x1c #define PHY_EXT_PAGE_ACCESS 0x1f +#define PHY_EXT_PAGE_ACCESS_GENERAL 0x10 +#define PHY_EXT_PAGE_ACCESS_EXTENDED3 0x3 + +/* Vitesse VSC8574 control register */ +#define MIIM_VSC8574_MAC_SERDES_CON 0x10 +#define MIIM_VSC8574_MAC_SERDES_ANEG 0x80 +#define MIIM_VSC8574_GENERAL18 0x12 +#define MIIM_VSC8574_GENERAL19 0x13 + +/* Vitesse VSC8574 gerenal purpose register 18 */ +#define MIIM_VSC8574_18G_SGMII 0x80f0 +#define MIIM_VSC8574_18G_QSGMII 0x80e0 +#define MIIM_VSC8574_18G_CMDSTAT 0x8000 /* CIS8201 */ static int vitesse_config(struct phy_device *phydev) @@ -145,6 +158,49 @@ static int vsc8601_config(struct phy_device *phydev) return 0; } +static int vsc8574_config(struct phy_device *phydev) +{ + u32 val; + /* configure regiser 19G for MAC */ + phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, + PHY_EXT_PAGE_ACCESS_GENERAL); + + val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19); + if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) { + /* set bit 15:14 to '01' for QSGMII mode */ + val = (val & 0x3fff) | (1 << 14); + phy_write(phydev, MDIO_DEVAD_NONE, + MIIM_VSC8574_GENERAL19, val); + /* Enable 4 ports MAC QSGMII */ + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18, + MIIM_VSC8574_18G_QSGMII); + } else { + /* set bit 15:14 to '00' for SGMII mode */ + val = val & 0x3fff; + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19, val); + /* Enable 4 ports MAC SGMII */ + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18, + MIIM_VSC8574_18G_SGMII); + } + val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18); + /* When bit 15 is cleared the command has completed */ + while (val & MIIM_VSC8574_18G_CMDSTAT) + val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18); + + /* Enable Serdes Auto-negotiation */ + phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, + PHY_EXT_PAGE_ACCESS_EXTENDED3); + val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON); + val = val | MIIM_VSC8574_MAC_SERDES_ANEG; + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON, val); + + phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); + + genphy_config_aneg(phydev); + + return 0; +} + static struct phy_driver VSC8211_driver = { .name = "Vitesse VSC8211", .uid = 0xfc4b0, @@ -185,6 +241,16 @@ static struct phy_driver VSC8234_driver = { .shutdown = &genphy_shutdown, }; +static struct phy_driver VSC8574_driver = { + .name = "Vitesse VSC8574", + .uid = 0x704a0, + .mask = 0xffff0, + .features = PHY_GBIT_FEATURES, + .config = &vsc8574_config, + .startup = &vitesse_startup, + .shutdown = &genphy_shutdown, +}; + static struct phy_driver VSC8601_driver = { .name = "Vitesse VSC8601", .uid = 0x70420, @@ -244,6 +310,7 @@ int phy_vitesse_init(void) phy_register(&VSC8244_driver); phy_register(&VSC8211_driver); phy_register(&VSC8221_driver); + phy_register(&VSC8574_driver); phy_register(&VSC8662_driver); phy_register(&cis8201_driver); phy_register(&cis8204_driver); |