|
@@ -72,6 +72,10 @@
|
|
#define PHY_ID_VSC8572 0x000704d0
|
|
#define PHY_ID_VSC8572 0x000704d0
|
|
#define PHY_ID_VSC8574 0x000704a0
|
|
#define PHY_ID_VSC8574 0x000704a0
|
|
#define PHY_ID_VSC8601 0x00070420
|
|
#define PHY_ID_VSC8601 0x00070420
|
|
|
|
+#define PHY_ID_VSC7385 0x00070450
|
|
|
|
+#define PHY_ID_VSC7388 0x00070480
|
|
|
|
+#define PHY_ID_VSC7395 0x00070550
|
|
|
|
+#define PHY_ID_VSC7398 0x00070580
|
|
#define PHY_ID_VSC8662 0x00070660
|
|
#define PHY_ID_VSC8662 0x00070660
|
|
#define PHY_ID_VSC8221 0x000fc550
|
|
#define PHY_ID_VSC8221 0x000fc550
|
|
#define PHY_ID_VSC8211 0x000fc4b0
|
|
#define PHY_ID_VSC8211 0x000fc4b0
|
|
@@ -116,6 +120,137 @@ static int vsc824x_config_init(struct phy_device *phydev)
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#define VSC73XX_EXT_PAGE_ACCESS 0x1f
|
|
|
|
+
|
|
|
|
+static int vsc73xx_read_page(struct phy_device *phydev)
|
|
|
|
+{
|
|
|
|
+ return __phy_read(phydev, VSC73XX_EXT_PAGE_ACCESS);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vsc73xx_write_page(struct phy_device *phydev, int page)
|
|
|
|
+{
|
|
|
|
+ return __phy_write(phydev, VSC73XX_EXT_PAGE_ACCESS, page);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void vsc73xx_config_init(struct phy_device *phydev)
|
|
|
|
+{
|
|
|
|
+ /* Receiver init */
|
|
|
|
+ phy_write(phydev, 0x1f, 0x2a30);
|
|
|
|
+ phy_modify(phydev, 0x0c, 0x0300, 0x0200);
|
|
|
|
+ phy_write(phydev, 0x1f, 0x0000);
|
|
|
|
+
|
|
|
|
+ /* Config LEDs 0x61 */
|
|
|
|
+ phy_modify(phydev, MII_TPISTATUS, 0xff00, 0x0061);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vsc738x_config_init(struct phy_device *phydev)
|
|
|
|
+{
|
|
|
|
+ u16 rev;
|
|
|
|
+ /* This magic sequence appear in the application note
|
|
|
|
+ * "VSC7385/7388 PHY Configuration".
|
|
|
|
+ *
|
|
|
|
+ * Maybe one day we will get to know what it all means.
|
|
|
|
+ */
|
|
|
|
+ phy_write(phydev, 0x1f, 0x2a30);
|
|
|
|
+ phy_modify(phydev, 0x08, 0x0200, 0x0200);
|
|
|
|
+ phy_write(phydev, 0x1f, 0x52b5);
|
|
|
|
+ phy_write(phydev, 0x10, 0xb68a);
|
|
|
|
+ phy_modify(phydev, 0x12, 0xff07, 0x0003);
|
|
|
|
+ phy_modify(phydev, 0x11, 0x00ff, 0x00a2);
|
|
|
|
+ phy_write(phydev, 0x10, 0x968a);
|
|
|
|
+ phy_write(phydev, 0x1f, 0x2a30);
|
|
|
|
+ phy_modify(phydev, 0x08, 0x0200, 0x0000);
|
|
|
|
+ phy_write(phydev, 0x1f, 0x0000);
|
|
|
|
+
|
|
|
|
+ /* Read revision */
|
|
|
|
+ rev = phy_read(phydev, MII_PHYSID2);
|
|
|
|
+ rev &= 0x0f;
|
|
|
|
+
|
|
|
|
+ /* Special quirk for revision 0 */
|
|
|
|
+ if (rev == 0) {
|
|
|
|
+ phy_write(phydev, 0x1f, 0x2a30);
|
|
|
|
+ phy_modify(phydev, 0x08, 0x0200, 0x0200);
|
|
|
|
+ phy_write(phydev, 0x1f, 0x52b5);
|
|
|
|
+ phy_write(phydev, 0x12, 0x0000);
|
|
|
|
+ phy_write(phydev, 0x11, 0x0689);
|
|
|
|
+ phy_write(phydev, 0x10, 0x8f92);
|
|
|
|
+ phy_write(phydev, 0x1f, 0x52b5);
|
|
|
|
+ phy_write(phydev, 0x12, 0x0000);
|
|
|
|
+ phy_write(phydev, 0x11, 0x0e35);
|
|
|
|
+ phy_write(phydev, 0x10, 0x9786);
|
|
|
|
+ phy_write(phydev, 0x1f, 0x2a30);
|
|
|
|
+ phy_modify(phydev, 0x08, 0x0200, 0x0000);
|
|
|
|
+ phy_write(phydev, 0x17, 0xff80);
|
|
|
|
+ phy_write(phydev, 0x17, 0x0000);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ phy_write(phydev, 0x1f, 0x0000);
|
|
|
|
+ phy_write(phydev, 0x12, 0x0048);
|
|
|
|
+
|
|
|
|
+ if (rev == 0) {
|
|
|
|
+ phy_write(phydev, 0x1f, 0x2a30);
|
|
|
|
+ phy_write(phydev, 0x14, 0x6600);
|
|
|
|
+ phy_write(phydev, 0x1f, 0x0000);
|
|
|
|
+ phy_write(phydev, 0x18, 0xa24e);
|
|
|
|
+ } else {
|
|
|
|
+ phy_write(phydev, 0x1f, 0x2a30);
|
|
|
|
+ phy_modify(phydev, 0x16, 0x0fc0, 0x0240);
|
|
|
|
+ phy_modify(phydev, 0x14, 0x6000, 0x4000);
|
|
|
|
+ /* bits 14-15 in extended register 0x14 controls DACG amplitude
|
|
|
|
+ * 6 = -8%, 2 is hardware default
|
|
|
|
+ */
|
|
|
|
+ phy_write(phydev, 0x1f, 0x0001);
|
|
|
|
+ phy_modify(phydev, 0x14, 0xe000, 0x6000);
|
|
|
|
+ phy_write(phydev, 0x1f, 0x0000);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ vsc73xx_config_init(phydev);
|
|
|
|
+
|
|
|
|
+ return genphy_config_init(phydev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vsc739x_config_init(struct phy_device *phydev)
|
|
|
|
+{
|
|
|
|
+ /* This magic sequence appears in the VSC7395 SparX-G5e application
|
|
|
|
+ * note "VSC7395/VSC7398 PHY Configuration"
|
|
|
|
+ *
|
|
|
|
+ * Maybe one day we will get to know what it all means.
|
|
|
|
+ */
|
|
|
|
+ phy_write(phydev, 0x1f, 0x2a30);
|
|
|
|
+ phy_modify(phydev, 0x08, 0x0200, 0x0200);
|
|
|
|
+ phy_write(phydev, 0x1f, 0x52b5);
|
|
|
|
+ phy_write(phydev, 0x10, 0xb68a);
|
|
|
|
+ phy_modify(phydev, 0x12, 0xff07, 0x0003);
|
|
|
|
+ phy_modify(phydev, 0x11, 0x00ff, 0x00a2);
|
|
|
|
+ phy_write(phydev, 0x10, 0x968a);
|
|
|
|
+ phy_write(phydev, 0x1f, 0x2a30);
|
|
|
|
+ phy_modify(phydev, 0x08, 0x0200, 0x0000);
|
|
|
|
+ phy_write(phydev, 0x1f, 0x0000);
|
|
|
|
+
|
|
|
|
+ phy_write(phydev, 0x1f, 0x0000);
|
|
|
|
+ phy_write(phydev, 0x12, 0x0048);
|
|
|
|
+ phy_write(phydev, 0x1f, 0x2a30);
|
|
|
|
+ phy_modify(phydev, 0x16, 0x0fc0, 0x0240);
|
|
|
|
+ phy_modify(phydev, 0x14, 0x6000, 0x4000);
|
|
|
|
+ phy_write(phydev, 0x1f, 0x0001);
|
|
|
|
+ phy_modify(phydev, 0x14, 0xe000, 0x6000);
|
|
|
|
+ phy_write(phydev, 0x1f, 0x0000);
|
|
|
|
+
|
|
|
|
+ vsc73xx_config_init(phydev);
|
|
|
|
+
|
|
|
|
+ return genphy_config_init(phydev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vsc73xx_config_aneg(struct phy_device *phydev)
|
|
|
|
+{
|
|
|
|
+ /* The VSC73xx switches does not like to be instructed to
|
|
|
|
+ * do autonegotiation in any way, it prefers that you just go
|
|
|
|
+ * with the power-on/reset defaults. Writing some registers will
|
|
|
|
+ * just make autonegotiation permanently fail.
|
|
|
|
+ */
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
/* This adds a skew for both TX and RX clocks, so the skew should only be
|
|
/* This adds a skew for both TX and RX clocks, so the skew should only be
|
|
* applied to "rgmii-id" interfaces. It may not work as expected
|
|
* applied to "rgmii-id" interfaces. It may not work as expected
|
|
* on "rgmii-txid", "rgmii-rxid" or "rgmii" interfaces. */
|
|
* on "rgmii-txid", "rgmii-rxid" or "rgmii" interfaces. */
|
|
@@ -318,6 +453,42 @@ static struct phy_driver vsc82xx_driver[] = {
|
|
.config_init = &vsc8601_config_init,
|
|
.config_init = &vsc8601_config_init,
|
|
.ack_interrupt = &vsc824x_ack_interrupt,
|
|
.ack_interrupt = &vsc824x_ack_interrupt,
|
|
.config_intr = &vsc82xx_config_intr,
|
|
.config_intr = &vsc82xx_config_intr,
|
|
|
|
+}, {
|
|
|
|
+ .phy_id = PHY_ID_VSC7385,
|
|
|
|
+ .name = "Vitesse VSC7385",
|
|
|
|
+ .phy_id_mask = 0x000ffff0,
|
|
|
|
+ .features = PHY_GBIT_FEATURES,
|
|
|
|
+ .config_init = vsc738x_config_init,
|
|
|
|
+ .config_aneg = vsc73xx_config_aneg,
|
|
|
|
+ .read_page = vsc73xx_read_page,
|
|
|
|
+ .write_page = vsc73xx_write_page,
|
|
|
|
+}, {
|
|
|
|
+ .phy_id = PHY_ID_VSC7388,
|
|
|
|
+ .name = "Vitesse VSC7388",
|
|
|
|
+ .phy_id_mask = 0x000ffff0,
|
|
|
|
+ .features = PHY_GBIT_FEATURES,
|
|
|
|
+ .config_init = vsc738x_config_init,
|
|
|
|
+ .config_aneg = vsc73xx_config_aneg,
|
|
|
|
+ .read_page = vsc73xx_read_page,
|
|
|
|
+ .write_page = vsc73xx_write_page,
|
|
|
|
+}, {
|
|
|
|
+ .phy_id = PHY_ID_VSC7395,
|
|
|
|
+ .name = "Vitesse VSC7395",
|
|
|
|
+ .phy_id_mask = 0x000ffff0,
|
|
|
|
+ .features = PHY_GBIT_FEATURES,
|
|
|
|
+ .config_init = vsc739x_config_init,
|
|
|
|
+ .config_aneg = vsc73xx_config_aneg,
|
|
|
|
+ .read_page = vsc73xx_read_page,
|
|
|
|
+ .write_page = vsc73xx_write_page,
|
|
|
|
+}, {
|
|
|
|
+ .phy_id = PHY_ID_VSC7398,
|
|
|
|
+ .name = "Vitesse VSC7398",
|
|
|
|
+ .phy_id_mask = 0x000ffff0,
|
|
|
|
+ .features = PHY_GBIT_FEATURES,
|
|
|
|
+ .config_init = vsc739x_config_init,
|
|
|
|
+ .config_aneg = vsc73xx_config_aneg,
|
|
|
|
+ .read_page = vsc73xx_read_page,
|
|
|
|
+ .write_page = vsc73xx_write_page,
|
|
}, {
|
|
}, {
|
|
.phy_id = PHY_ID_VSC8662,
|
|
.phy_id = PHY_ID_VSC8662,
|
|
.name = "Vitesse VSC8662",
|
|
.name = "Vitesse VSC8662",
|
|
@@ -358,6 +529,10 @@ static struct mdio_device_id __maybe_unused vitesse_tbl[] = {
|
|
{ PHY_ID_VSC8514, 0x000ffff0 },
|
|
{ PHY_ID_VSC8514, 0x000ffff0 },
|
|
{ PHY_ID_VSC8572, 0x000ffff0 },
|
|
{ PHY_ID_VSC8572, 0x000ffff0 },
|
|
{ PHY_ID_VSC8574, 0x000ffff0 },
|
|
{ PHY_ID_VSC8574, 0x000ffff0 },
|
|
|
|
+ { PHY_ID_VSC7385, 0x000ffff0 },
|
|
|
|
+ { PHY_ID_VSC7388, 0x000ffff0 },
|
|
|
|
+ { PHY_ID_VSC7395, 0x000ffff0 },
|
|
|
|
+ { PHY_ID_VSC7398, 0x000ffff0 },
|
|
{ PHY_ID_VSC8662, 0x000ffff0 },
|
|
{ PHY_ID_VSC8662, 0x000ffff0 },
|
|
{ PHY_ID_VSC8221, 0x000ffff0 },
|
|
{ PHY_ID_VSC8221, 0x000ffff0 },
|
|
{ PHY_ID_VSC8211, 0x000ffff0 },
|
|
{ PHY_ID_VSC8211, 0x000ffff0 },
|