|
@@ -48,6 +48,19 @@
|
|
#define MIIM_VSC8601_SKEW_CTRL 0x1c
|
|
#define MIIM_VSC8601_SKEW_CTRL 0x1c
|
|
|
|
|
|
#define PHY_EXT_PAGE_ACCESS 0x1f
|
|
#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 */
|
|
/* CIS8201 */
|
|
static int vitesse_config(struct phy_device *phydev)
|
|
static int vitesse_config(struct phy_device *phydev)
|
|
@@ -145,6 +158,49 @@ static int vsc8601_config(struct phy_device *phydev)
|
|
return 0;
|
|
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 = {
|
|
static struct phy_driver VSC8211_driver = {
|
|
.name = "Vitesse VSC8211",
|
|
.name = "Vitesse VSC8211",
|
|
.uid = 0xfc4b0,
|
|
.uid = 0xfc4b0,
|
|
@@ -185,6 +241,16 @@ static struct phy_driver VSC8234_driver = {
|
|
.shutdown = &genphy_shutdown,
|
|
.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 = {
|
|
static struct phy_driver VSC8601_driver = {
|
|
.name = "Vitesse VSC8601",
|
|
.name = "Vitesse VSC8601",
|
|
.uid = 0x70420,
|
|
.uid = 0x70420,
|
|
@@ -244,6 +310,7 @@ int phy_vitesse_init(void)
|
|
phy_register(&VSC8244_driver);
|
|
phy_register(&VSC8244_driver);
|
|
phy_register(&VSC8211_driver);
|
|
phy_register(&VSC8211_driver);
|
|
phy_register(&VSC8221_driver);
|
|
phy_register(&VSC8221_driver);
|
|
|
|
+ phy_register(&VSC8574_driver);
|
|
phy_register(&VSC8662_driver);
|
|
phy_register(&VSC8662_driver);
|
|
phy_register(&cis8201_driver);
|
|
phy_register(&cis8201_driver);
|
|
phy_register(&cis8204_driver);
|
|
phy_register(&cis8204_driver);
|