From 4035e812247e9146cda1bcac3d109dc2fdc35d84 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 19 Mar 2020 23:16:46 +0200 Subject: [PATCH 1/4] net: phy: mscc: rename enum rgmii_rx_clock_delay to rgmii_clock_delay There is nothing RX-specific about these clock skew values. So remove "RX" from the name in preparation for the next patch where TX delays are also going to be configured. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/mscc/mscc.h | 18 +++++++++--------- drivers/net/phy/mscc/mscc_main.c | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h index 25729302714c8..99e2d20596ad9 100644 --- a/drivers/net/phy/mscc/mscc.h +++ b/drivers/net/phy/mscc/mscc.h @@ -12,15 +12,15 @@ #include "mscc_macsec.h" #endif -enum rgmii_rx_clock_delay { - RGMII_RX_CLK_DELAY_0_2_NS = 0, - RGMII_RX_CLK_DELAY_0_8_NS = 1, - RGMII_RX_CLK_DELAY_1_1_NS = 2, - RGMII_RX_CLK_DELAY_1_7_NS = 3, - RGMII_RX_CLK_DELAY_2_0_NS = 4, - RGMII_RX_CLK_DELAY_2_3_NS = 5, - RGMII_RX_CLK_DELAY_2_6_NS = 6, - RGMII_RX_CLK_DELAY_3_4_NS = 7 +enum rgmii_clock_delay { + RGMII_CLK_DELAY_0_2_NS = 0, + RGMII_CLK_DELAY_0_8_NS = 1, + RGMII_CLK_DELAY_1_1_NS = 2, + RGMII_CLK_DELAY_1_7_NS = 3, + RGMII_CLK_DELAY_2_0_NS = 4, + RGMII_CLK_DELAY_2_3_NS = 5, + RGMII_CLK_DELAY_2_6_NS = 6, + RGMII_CLK_DELAY_3_4_NS = 7 }; /* Microsemi VSC85xx PHY registers */ diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index 5d78732de7020..3aaf03723fa7d 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -525,7 +525,7 @@ static int vsc85xx_default_config(struct phy_device *phydev) phydev->mdix_ctrl = ETH_TP_MDI_AUTO; mutex_lock(&phydev->lock); - reg_val = RGMII_RX_CLK_DELAY_1_1_NS << RGMII_RX_CLK_DELAY_POS; + reg_val = RGMII_CLK_DELAY_1_1_NS << RGMII_RX_CLK_DELAY_POS; rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2, MSCC_PHY_RGMII_CNTL, RGMII_RX_CLK_DELAY_MASK, From da206d65f2b293274f8082a26da4e43a1610da54 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 19 Mar 2020 23:16:47 +0200 Subject: [PATCH 2/4] net: phy: mscc: accept all RGMII species in vsc85xx_mac_if_set The helper for configuring the pinout of the MII side of the PHY should do so irrespective of whether RGMII delays are used or not. So accept the ID, TXID and RXID variants as well, not just the no-delay RGMII variant. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/mscc/mscc_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index 3aaf03723fa7d..c1aaf9f8b2432 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -491,6 +491,9 @@ static int vsc85xx_mac_if_set(struct phy_device *phydev, reg_val = phy_read(phydev, MSCC_PHY_EXT_PHY_CNTL_1); reg_val &= ~(MAC_IF_SELECTION_MASK); switch (interface) { + case PHY_INTERFACE_MODE_RGMII_TXID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII: reg_val |= (MAC_IF_SELECTION_RGMII << MAC_IF_SELECTION_POS); break; From 7b005a1742be4608480d9d151aec42170a06cbee Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 19 Mar 2020 23:16:48 +0200 Subject: [PATCH 3/4] net: phy: mscc: configure both RX and TX internal delays for RGMII The driver appears to be secretly enabling the RX clock skew irrespective of PHY interface type, which is generally considered a big no-no. Make them configurable instead, and add TX internal delays when necessary too. While at it, configure a more canonical clock skew of 2.0 nanoseconds than the current default of 1.1 ns. Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/phy/mscc/mscc.h | 2 ++ drivers/net/phy/mscc/mscc_main.c | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h index 99e2d20596ad9..0f04afd81816e 100644 --- a/drivers/net/phy/mscc/mscc.h +++ b/drivers/net/phy/mscc/mscc.h @@ -178,6 +178,8 @@ enum rgmii_clock_delay { #define MSCC_PHY_RGMII_CNTL 20 #define RGMII_RX_CLK_DELAY_MASK 0x0070 #define RGMII_RX_CLK_DELAY_POS 4 +#define RGMII_TX_CLK_DELAY_MASK 0x0007 +#define RGMII_TX_CLK_DELAY_POS 0 #define MSCC_PHY_WOL_LOWER_MAC_ADDR 21 #define MSCC_PHY_WOL_MID_MAC_ADDR 22 diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index c1aaf9f8b2432..c162fbaec1d75 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -522,16 +522,26 @@ static int vsc85xx_mac_if_set(struct phy_device *phydev, static int vsc85xx_default_config(struct phy_device *phydev) { + u16 reg_val = 0; int rc; - u16 reg_val; phydev->mdix_ctrl = ETH_TP_MDI_AUTO; + + if (!phy_interface_mode_is_rgmii(phydev->interface)) + return 0; + mutex_lock(&phydev->lock); - reg_val = RGMII_CLK_DELAY_1_1_NS << RGMII_RX_CLK_DELAY_POS; + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + reg_val |= RGMII_CLK_DELAY_2_0_NS << RGMII_RX_CLK_DELAY_POS; + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + reg_val |= RGMII_CLK_DELAY_2_0_NS << RGMII_TX_CLK_DELAY_POS; rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2, - MSCC_PHY_RGMII_CNTL, RGMII_RX_CLK_DELAY_MASK, + MSCC_PHY_RGMII_CNTL, + RGMII_RX_CLK_DELAY_MASK | RGMII_TX_CLK_DELAY_MASK, reg_val); mutex_unlock(&phydev->lock); From d3169863310d151b5fb42b08de009ea8f2788264 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 19 Mar 2020 23:16:49 +0200 Subject: [PATCH 4/4] net: phy: mscc: add support for VSC8502 This is a dual copper PHY with support for MII/GMII/RGMII on MAC side, as well as a bunch of other features such as SyncE and Ring Resiliency. I haven't tested interrupts and WoL, but I am confident that they work since support is already present in the driver and the register map is no different for this PHY. PHY statistics work, PHY tunables appear to work, suspend/resume works. Signed-off-by: Wes Li Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/phy/mscc/mscc.h | 1 + drivers/net/phy/mscc/mscc_main.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h index 0f04afd81816e..d983d3af66d61 100644 --- a/drivers/net/phy/mscc/mscc.h +++ b/drivers/net/phy/mscc/mscc.h @@ -276,6 +276,7 @@ enum rgmii_clock_delay { /* Microsemi PHY ID's * Code assumes lowest nibble is 0 */ +#define PHY_ID_VSC8502 0x00070630 #define PHY_ID_VSC8504 0x000704c0 #define PHY_ID_VSC8514 0x00070670 #define PHY_ID_VSC8530 0x00070560 diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index c162fbaec1d75..19603081dd146 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -2089,6 +2089,30 @@ static int vsc85xx_probe(struct phy_device *phydev) /* Microsemi VSC85xx PHYs */ static struct phy_driver vsc85xx_driver[] = { +{ + .phy_id = PHY_ID_VSC8502, + .name = "Microsemi GE VSC8502 SyncE", + .phy_id_mask = 0xfffffff0, + /* PHY_BASIC_FEATURES */ + .soft_reset = &genphy_soft_reset, + .config_init = &vsc85xx_config_init, + .config_aneg = &vsc85xx_config_aneg, + .read_status = &vsc85xx_read_status, + .ack_interrupt = &vsc85xx_ack_interrupt, + .config_intr = &vsc85xx_config_intr, + .suspend = &genphy_suspend, + .resume = &genphy_resume, + .probe = &vsc85xx_probe, + .set_wol = &vsc85xx_wol_set, + .get_wol = &vsc85xx_wol_get, + .get_tunable = &vsc85xx_get_tunable, + .set_tunable = &vsc85xx_set_tunable, + .read_page = &vsc85xx_phy_read_page, + .write_page = &vsc85xx_phy_write_page, + .get_sset_count = &vsc85xx_get_sset_count, + .get_strings = &vsc85xx_get_strings, + .get_stats = &vsc85xx_get_stats, +}, { .phy_id = PHY_ID_VSC8504, .name = "Microsemi GE VSC8504 SyncE",