From: Scott Roberts Date: Fri, 27 Sep 2019 20:19:01 +0000 (-0600) Subject: mvebu: backport mvneta and comphy from linux 5.x X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=d2a1075973728b55231688809b68a0f0b93c9da4;p=openwrt%2Fstaging%2Fluka.git mvebu: backport mvneta and comphy from linux 5.x These patches backport support for the ARMADA 3700 COMPHY driver. Also backported is the mvneta driver. This will allow switching the SGMII speed using SMC calls. To support this you must update the firmware using Marvells 18.12 version (this has now been upstreamed). The mvneta driver allows 2500basex and 2500baset. Signed-off-by: Scott Roberts --- diff --git a/target/linux/mvebu/config-4.19 b/target/linux/mvebu/config-4.19 index 45fac6f0c1..4f1ef188ef 100644 --- a/target/linux/mvebu/config-4.19 +++ b/target/linux/mvebu/config-4.19 @@ -391,6 +391,7 @@ CONFIG_PERF_USE_VMALLOC=y CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y CONFIG_PHYLINK=y +# CONFIG_PHY_MVEBU_A3700_COMPHY is not set # CONFIG_PHY_MVEBU_CP110_COMPHY is not set CONFIG_PINCTRL=y CONFIG_PINCTRL_ARMADA_370=y diff --git a/target/linux/mvebu/cortexa53/config-4.19 b/target/linux/mvebu/cortexa53/config-4.19 index 445192e717..7f3c2b21de 100644 --- a/target/linux/mvebu/cortexa53/config-4.19 +++ b/target/linux/mvebu/cortexa53/config-4.19 @@ -143,6 +143,7 @@ CONFIG_PARTITION_PERCPU=y CONFIG_PCI_AARDVARK=y CONFIG_PGTABLE_LEVELS=3 CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PHY_MVEBU_A3700_COMPHY=y CONFIG_PINCTRL_ARMADA_37XX=y CONFIG_PINCTRL_ARMADA_AP806=y CONFIG_PINCTRL_ARMADA_CP110=y diff --git a/target/linux/mvebu/patches-4.19/531-net-mvneta-Add-support-for-2500Mbps-SGMII.patch b/target/linux/mvebu/patches-4.19/531-net-mvneta-Add-support-for-2500Mbps-SGMII.patch new file mode 100644 index 0000000000..0368ba9509 --- /dev/null +++ b/target/linux/mvebu/patches-4.19/531-net-mvneta-Add-support-for-2500Mbps-SGMII.patch @@ -0,0 +1,104 @@ +From da58a931f248f423f917c3a0b3c94303aa30a738 Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Tue, 25 Sep 2018 15:59:39 +0200 +Subject: [PATCH] net: mvneta: Add support for 2500Mbps SGMII + +The mvneta controller can handle speeds up to 2500Mbps on the SGMII +interface. This relies on serdes configuration, the lane must be +configured at 3.125Gbps and we can't use in-band autoneg at that speed. + +The main issue when supporting that speed on this particular controller +is that the link partner can send ethernet frames with a shortened +preamble, which if not explicitly enabled in the controller will cause +unexpected behaviours. + +This was tested on Armada 385, with the comphy configuration done in +bootloader. + +Signed-off-by: Maxime Chevallier +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/marvell/mvneta.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -221,6 +221,8 @@ + #define MVNETA_GMAC_AN_FLOW_CTRL_EN BIT(11) + #define MVNETA_GMAC_CONFIG_FULL_DUPLEX BIT(12) + #define MVNETA_GMAC_AN_DUPLEX_EN BIT(13) ++#define MVNETA_GMAC_CTRL_4 0x2c90 ++#define MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE BIT(1) + #define MVNETA_MIB_COUNTERS_BASE 0x3000 + #define MVNETA_MIB_LATE_COLLISION 0x7c + #define MVNETA_DA_FILT_SPEC_MCAST 0x3400 +@@ -3344,6 +3346,7 @@ static void mvneta_validate(struct net_d + if (state->interface != PHY_INTERFACE_MODE_NA && + state->interface != PHY_INTERFACE_MODE_QSGMII && + state->interface != PHY_INTERFACE_MODE_SGMII && ++ state->interface != PHY_INTERFACE_MODE_2500BASEX && + !phy_interface_mode_is_8023z(state->interface) && + !phy_interface_mode_is_rgmii(state->interface)) { + bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); +@@ -3356,9 +3359,15 @@ static void mvneta_validate(struct net_d + + /* Asymmetric pause is unsupported */ + phylink_set(mask, Pause); +- /* Half-duplex at speeds higher than 100Mbit is unsupported */ +- phylink_set(mask, 1000baseT_Full); +- phylink_set(mask, 1000baseX_Full); ++ ++ /* We cannot use 1Gbps when using the 2.5G interface. */ ++ if (state->interface == PHY_INTERFACE_MODE_2500BASEX) { ++ phylink_set(mask, 2500baseT_Full); ++ phylink_set(mask, 2500baseX_Full); ++ } else { ++ phylink_set(mask, 1000baseT_Full); ++ phylink_set(mask, 1000baseX_Full); ++ } + + if (!phy_interface_mode_is_8023z(state->interface)) { + /* 10M and 100M are only supported in non-802.3z mode */ +@@ -3419,12 +3428,14 @@ static void mvneta_mac_config(struct net + struct mvneta_port *pp = netdev_priv(ndev); + u32 new_ctrl0, gmac_ctrl0 = mvreg_read(pp, MVNETA_GMAC_CTRL_0); + u32 new_ctrl2, gmac_ctrl2 = mvreg_read(pp, MVNETA_GMAC_CTRL_2); ++ u32 new_ctrl4, gmac_ctrl4 = mvreg_read(pp, MVNETA_GMAC_CTRL_4); + u32 new_clk, gmac_clk = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); + u32 new_an, gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); + + new_ctrl0 = gmac_ctrl0 & ~MVNETA_GMAC0_PORT_1000BASE_X; + new_ctrl2 = gmac_ctrl2 & ~(MVNETA_GMAC2_INBAND_AN_ENABLE | + MVNETA_GMAC2_PORT_RESET); ++ new_ctrl4 = gmac_ctrl4 & ~(MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE); + new_clk = gmac_clk & ~MVNETA_GMAC_1MS_CLOCK_ENABLE; + new_an = gmac_an & ~(MVNETA_GMAC_INBAND_AN_ENABLE | + MVNETA_GMAC_INBAND_RESTART_AN | +@@ -3457,7 +3468,7 @@ static void mvneta_mac_config(struct net + if (state->duplex) + new_an |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; + +- if (state->speed == SPEED_1000) ++ if (state->speed == SPEED_1000 || state->speed == SPEED_2500) + new_an |= MVNETA_GMAC_CONFIG_GMII_SPEED; + else if (state->speed == SPEED_100) + new_an |= MVNETA_GMAC_CONFIG_MII_SPEED; +@@ -3496,10 +3507,18 @@ static void mvneta_mac_config(struct net + MVNETA_GMAC_FORCE_LINK_DOWN); + } + ++ /* When at 2.5G, the link partner can send frames with shortened ++ * preambles. ++ */ ++ if (state->speed == SPEED_2500) ++ new_ctrl4 |= MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE; ++ + if (new_ctrl0 != gmac_ctrl0) + mvreg_write(pp, MVNETA_GMAC_CTRL_0, new_ctrl0); + if (new_ctrl2 != gmac_ctrl2) + mvreg_write(pp, MVNETA_GMAC_CTRL_2, new_ctrl2); ++ if (new_ctrl4 != gmac_ctrl4) ++ mvreg_write(pp, MVNETA_GMAC_CTRL_4, new_ctrl4); + if (new_clk != gmac_clk) + mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, new_clk); + if (new_an != gmac_an) diff --git a/target/linux/mvebu/patches-4.19/532-net-mvneta-correct-typo.patch b/target/linux/mvebu/patches-4.19/532-net-mvneta-correct-typo.patch new file mode 100644 index 0000000000..bff7621fa4 --- /dev/null +++ b/target/linux/mvebu/patches-4.19/532-net-mvneta-correct-typo.patch @@ -0,0 +1,33 @@ +From fbd1d5245372e48b494120a30fe0b34b304576c4 Mon Sep 17 00:00:00 2001 +From: Alexandre Belloni +Date: Fri, 9 Nov 2018 17:37:20 +0100 +Subject: [PATCH] net: mvneta: correct typo + +The reserved variable should be named reserved1. + +Signed-off-by: Alexandre Belloni +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/marvell/mvneta.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -493,7 +493,7 @@ struct mvneta_port { + #if defined(__LITTLE_ENDIAN) + struct mvneta_tx_desc { + u32 command; /* Options used by HW for packet transmitting.*/ +- u16 reserverd1; /* csum_l4 (for future use) */ ++ u16 reserved1; /* csum_l4 (for future use) */ + u16 data_size; /* Data size of transmitted packet in bytes */ + u32 buf_phys_addr; /* Physical addr of transmitted buffer */ + u32 reserved2; /* hw_cmd - (for future use, PMT) */ +@@ -518,7 +518,7 @@ struct mvneta_rx_desc { + #else + struct mvneta_tx_desc { + u16 data_size; /* Data size of transmitted packet in bytes */ +- u16 reserverd1; /* csum_l4 (for future use) */ ++ u16 reserved1; /* csum_l4 (for future use) */ + u32 command; /* Options used by HW for packet transmitting.*/ + u32 reserved2; /* hw_cmd - (for future use, PMT) */ + u32 buf_phys_addr; /* Physical addr of transmitted buffer */ diff --git a/target/linux/mvebu/patches-4.19/533-net-mvneta-Dont-advertise-2.5G-modes.patch b/target/linux/mvebu/patches-4.19/533-net-mvneta-Dont-advertise-2.5G-modes.patch new file mode 100644 index 0000000000..31292a638e --- /dev/null +++ b/target/linux/mvebu/patches-4.19/533-net-mvneta-Dont-advertise-2.5G-modes.patch @@ -0,0 +1,55 @@ +From 83e65df6dfece9eb588735459428f221eb930c0c Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Fri, 9 Nov 2018 09:17:33 +0100 +Subject: [PATCH] net: mvneta: Don't advertise 2.5G modes + +Using 2.5G speed relies on the SerDes lanes being configured +accordingly. The lanes have to be reconfigured to switch between +1G and 2.5G, and for now only the bootloader does this configuration. + +In the case we add a Comphy driver to handle switching the lanes +dynamically, it's better for now to stick with supporting only 1G and +add advertisement for 2.5G once we really are capable of handling both +speeds without problem. + +Since the interface mode is initialy taken from the DT, we want to make +sure that adding comphy support won't break boards that don't update +their dtb. + +Fixes: da58a931f248 ("net: mvneta: Add support for 2500Mbps SGMII") +Reported-by: Andrew Lunn +Reported-by: Russell King +Signed-off-by: Maxime Chevallier +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/marvell/mvneta.c | 12 +++--------- + 1 file changed, 3 insertions(+), 9 deletions(-) + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -3346,7 +3346,6 @@ static void mvneta_validate(struct net_d + if (state->interface != PHY_INTERFACE_MODE_NA && + state->interface != PHY_INTERFACE_MODE_QSGMII && + state->interface != PHY_INTERFACE_MODE_SGMII && +- state->interface != PHY_INTERFACE_MODE_2500BASEX && + !phy_interface_mode_is_8023z(state->interface) && + !phy_interface_mode_is_rgmii(state->interface)) { + bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); +@@ -3360,14 +3359,9 @@ static void mvneta_validate(struct net_d + /* Asymmetric pause is unsupported */ + phylink_set(mask, Pause); + +- /* We cannot use 1Gbps when using the 2.5G interface. */ +- if (state->interface == PHY_INTERFACE_MODE_2500BASEX) { +- phylink_set(mask, 2500baseT_Full); +- phylink_set(mask, 2500baseX_Full); +- } else { +- phylink_set(mask, 1000baseT_Full); +- phylink_set(mask, 1000baseX_Full); +- } ++ /* Half-duplex at speeds higher than 100Mbit is unsupported */ ++ phylink_set(mask, 1000baseT_Full); ++ phylink_set(mask, 1000baseX_Full); + + if (!phy_interface_mode_is_8023z(state->interface)) { + /* 10M and 100M are only supported in non-802.3z mode */ diff --git a/target/linux/mvebu/patches-4.19/534-net-mvneta-remove-redundant-check-for.patch b/target/linux/mvebu/patches-4.19/534-net-mvneta-remove-redundant-check-for.patch new file mode 100644 index 0000000000..005ea6e51e --- /dev/null +++ b/target/linux/mvebu/patches-4.19/534-net-mvneta-remove-redundant-check-for.patch @@ -0,0 +1,30 @@ +From e4a3e9ff5ba9f6b67595ec2768ed4be2054c2aa5 Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Thu, 22 Nov 2018 14:42:00 +0800 +Subject: [PATCH] net: mvneta: remove redundant check for + eee->tx_lpi_timer < 0 + +fixes the smatch warning: + +drivers/net/ethernet/marvell/mvneta.c:4252 mvneta_ethtool_set_eee() warn: + unsigned 'eee->tx_lpi_timer' is never less than zero. + +Signed-off-by: YueHaibing +Acked-by: Thomas Petazzoni +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/marvell/mvneta.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -4253,8 +4253,7 @@ static int mvneta_ethtool_set_eee(struct + + /* The Armada 37x documents do not give limits for this other than + * it being an 8-bit register. */ +- if (eee->tx_lpi_enabled && +- (eee->tx_lpi_timer < 0 || eee->tx_lpi_timer > 255)) ++ if (eee->tx_lpi_enabled && eee->tx_lpi_timer > 255) + return -EINVAL; + + lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0); diff --git a/target/linux/mvebu/patches-4.19/535-net-marvell-neta-add-comphy-support.patch b/target/linux/mvebu/patches-4.19/535-net-marvell-neta-add-comphy-support.patch new file mode 100644 index 0000000000..257cfdec4a --- /dev/null +++ b/target/linux/mvebu/patches-4.19/535-net-marvell-neta-add-comphy-support.patch @@ -0,0 +1,159 @@ +From a10c1c8191e04c21769656c2ca8e1c69a6218954 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Thu, 7 Feb 2019 16:19:26 +0000 +Subject: [PATCH] net: marvell: neta: add comphy support + +Add support for the common phy binding, so that we can reconfigure the +comphy according to the desired ethernet speed. This will allow us to +support 1000base-X and 2500base-X SFPs dynamically on SolidRun Clearfog. + +Signed-off-by: Russell King +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/marvell/mvneta.c | 45 +++++++++++++++++++++++++++++++---- + 1 file changed, 41 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -436,6 +437,7 @@ struct mvneta_port { + struct device_node *dn; + unsigned int tx_csum_limit; + struct phylink *phylink; ++ struct phy *comphy; + + struct mvneta_bm *bm_priv; + struct mvneta_bm_pool *pool_long; +@@ -3153,6 +3155,8 @@ static void mvneta_start_dev(struct mvne + { + int cpu; + ++ WARN_ON(phy_power_on(pp->comphy)); ++ + mvneta_max_rx_size_set(pp, pp->pkt_size); + mvneta_txq_max_tx_size_set(pp, pp->pkt_size); + +@@ -3215,6 +3219,8 @@ static void mvneta_stop_dev(struct mvnet + + mvneta_tx_reset(pp); + mvneta_rx_reset(pp); ++ ++ WARN_ON(phy_power_off(pp->comphy)); + } + + static void mvneta_percpu_enable(void *arg) +@@ -3340,6 +3346,7 @@ static int mvneta_set_mac_addr(struct ne + static void mvneta_validate(struct net_device *ndev, unsigned long *supported, + struct phylink_link_state *state) + { ++ struct mvneta_port *pp = netdev_priv(ndev); + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + + /* We only support QSGMII, SGMII, 802.3z and RGMII modes */ +@@ -3360,8 +3367,13 @@ static void mvneta_validate(struct net_d + phylink_set(mask, Pause); + + /* Half-duplex at speeds higher than 100Mbit is unsupported */ +- phylink_set(mask, 1000baseT_Full); +- phylink_set(mask, 1000baseX_Full); ++ if (pp->comphy || state->interface != PHY_INTERFACE_MODE_2500BASEX) { ++ phylink_set(mask, 1000baseT_Full); ++ phylink_set(mask, 1000baseX_Full); ++ } ++ if (pp->comphy || state->interface == PHY_INTERFACE_MODE_2500BASEX) { ++ phylink_set(mask, 2500baseX_Full); ++ } + + if (!phy_interface_mode_is_8023z(state->interface)) { + /* 10M and 100M are only supported in non-802.3z mode */ +@@ -3375,6 +3387,11 @@ static void mvneta_validate(struct net_d + __ETHTOOL_LINK_MODE_MASK_NBITS); + bitmap_and(state->advertising, state->advertising, mask, + __ETHTOOL_LINK_MODE_MASK_NBITS); ++ ++ /* We can only operate at 2500BaseX or 1000BaseX. If requested ++ * to advertise both, only report advertising at 2500BaseX. ++ */ ++ phylink_helper_basex_speed(state); + } + + static int mvneta_mac_link_state(struct net_device *ndev, +@@ -3386,7 +3403,9 @@ static int mvneta_mac_link_state(struct + gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS); + + if (gmac_stat & MVNETA_GMAC_SPEED_1000) +- state->speed = SPEED_1000; ++ state->speed = ++ state->interface == PHY_INTERFACE_MODE_2500BASEX ? ++ SPEED_2500 : SPEED_1000; + else if (gmac_stat & MVNETA_GMAC_SPEED_100) + state->speed = SPEED_100; + else +@@ -3501,12 +3520,20 @@ static void mvneta_mac_config(struct net + MVNETA_GMAC_FORCE_LINK_DOWN); + } + ++ + /* When at 2.5G, the link partner can send frames with shortened + * preambles. + */ + if (state->speed == SPEED_2500) + new_ctrl4 |= MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE; + ++ if (pp->comphy && ++ (state->interface == PHY_INTERFACE_MODE_SGMII || ++ state->interface == PHY_INTERFACE_MODE_1000BASEX || ++ state->interface == PHY_INTERFACE_MODE_2500BASEX)) ++ WARN_ON(phy_set_mode_ext(pp->comphy, PHY_MODE_ETHERNET, ++ state->interface)); ++ + if (new_ctrl0 != gmac_ctrl0) + mvreg_write(pp, MVNETA_GMAC_CTRL_0, new_ctrl0); + if (new_ctrl2 != gmac_ctrl2) +@@ -4419,7 +4446,7 @@ static int mvneta_port_power_up(struct m + if (phy_mode == PHY_INTERFACE_MODE_QSGMII) + mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_QSGMII_SERDES_PROTO); + else if (phy_mode == PHY_INTERFACE_MODE_SGMII || +- phy_mode == PHY_INTERFACE_MODE_1000BASEX) ++ phy_interface_mode_is_8023z(phy_mode)) + mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO); + else if (!phy_interface_mode_is_rgmii(phy_mode)) + return -EINVAL; +@@ -4436,6 +4463,7 @@ static int mvneta_probe(struct platform_ + struct mvneta_port *pp; + struct net_device *dev; + struct phylink *phylink; ++ struct phy *comphy; + const char *dt_mac_addr; + char hw_mac_addr[ETH_ALEN]; + const char *mac_from; +@@ -4461,6 +4489,14 @@ static int mvneta_probe(struct platform_ + goto err_free_irq; + } + ++ comphy = devm_of_phy_get(&pdev->dev, dn, NULL); ++ if (comphy == ERR_PTR(-EPROBE_DEFER)) { ++ err = -EPROBE_DEFER; ++ goto err_free_irq; ++ } else if (IS_ERR(comphy)) { ++ comphy = NULL; ++ } ++ + phylink = phylink_create(dev, pdev->dev.fwnode, phy_mode, + &mvneta_phylink_ops); + if (IS_ERR(phylink)) { +@@ -4477,6 +4513,7 @@ static int mvneta_probe(struct platform_ + pp = netdev_priv(dev); + spin_lock_init(&pp->lock); + pp->phylink = phylink; ++ pp->comphy = comphy; + pp->phy_interface = phy_mode; + pp->dn = dn; + diff --git a/target/linux/mvebu/patches-4.19/536-net-marvell-neta-disable-comphy-when-setting-mode.patch b/target/linux/mvebu/patches-4.19/536-net-marvell-neta-disable-comphy-when-setting-mode.patch new file mode 100644 index 0000000000..9abb00c50d --- /dev/null +++ b/target/linux/mvebu/patches-4.19/536-net-marvell-neta-disable-comphy-when-setting-mode.patch @@ -0,0 +1,78 @@ +From 031b922bfd60c771588911112f8632783de08e5c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 25 Feb 2019 17:43:03 +0100 +Subject: [PATCH] net: marvell: neta: disable comphy when setting mode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The comphy driver for Armada 3700 by Miquèl Raynal (which is currently +in linux-next) does not actually set comphy mode when phy_set_mode_ext +is called. The mode is set at next call of phy_power_on. + +Update the driver to semantics similar to mvpp2: helper +mvneta_comphy_init sets comphy mode and powers it on. +When mode is to be changed in mvneta_mac_config, first power the comphy +off, then call mvneta_comphy_init (which sets the mode to new one). + +Only do this when new mode is different from old mode. + +This should also work for Armada 38x, since in that comphy driver +methods power_on and power_off are unimplemented. + +Signed-off-by: Marek Behún +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/marvell/mvneta.c | 28 +++++++++++++++++++++++----- + 1 file changed, 23 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -3151,11 +3151,26 @@ static int mvneta_setup_txqs(struct mvne + return 0; + } + ++static int mvneta_comphy_init(struct mvneta_port *pp) ++{ ++ int ret; ++ ++ if (!pp->comphy) ++ return 0; ++ ++ ret = phy_set_mode_ext(pp->comphy, PHY_MODE_ETHERNET, ++ pp->phy_interface); ++ if (ret) ++ return ret; ++ ++ return phy_power_on(pp->comphy); ++} ++ + static void mvneta_start_dev(struct mvneta_port *pp) + { + int cpu; + +- WARN_ON(phy_power_on(pp->comphy)); ++ WARN_ON(mvneta_comphy_init(pp)); + + mvneta_max_rx_size_set(pp, pp->pkt_size); + mvneta_txq_max_tx_size_set(pp, pp->pkt_size); +@@ -3527,12 +3542,15 @@ static void mvneta_mac_config(struct net + if (state->speed == SPEED_2500) + new_ctrl4 |= MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE; + +- if (pp->comphy && ++ if (pp->comphy && pp->phy_interface != state->interface && + (state->interface == PHY_INTERFACE_MODE_SGMII || + state->interface == PHY_INTERFACE_MODE_1000BASEX || +- state->interface == PHY_INTERFACE_MODE_2500BASEX)) +- WARN_ON(phy_set_mode_ext(pp->comphy, PHY_MODE_ETHERNET, +- state->interface)); ++ state->interface == PHY_INTERFACE_MODE_2500BASEX)) { ++ pp->phy_interface = state->interface; ++ ++ WARN_ON(phy_power_off(pp->comphy)); ++ WARN_ON(mvneta_comphy_init(pp)); ++ } + + if (new_ctrl0 != gmac_ctrl0) + mvreg_write(pp, MVNETA_GMAC_CTRL_0, new_ctrl0); diff --git a/target/linux/mvebu/patches-4.19/537-net-mvneta-add-2500baset-support.patch b/target/linux/mvebu/patches-4.19/537-net-mvneta-add-2500baset-support.patch new file mode 100644 index 0000000000..6629547eef --- /dev/null +++ b/target/linux/mvebu/patches-4.19/537-net-mvneta-add-2500baset-support.patch @@ -0,0 +1,34 @@ +From eda3d1b0228484fb52b7244a68fd4cc8a985ed10 Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Wed, 27 Mar 2019 17:31:06 +0100 +Subject: [PATCH] net: mvneta: Add 2500BaseT support + +Some PHYs will use the 2500BaseX PHY_INTERFACE_MODE when being linked +with a partner using 2.5GBaseT. + +Since we can't autonegotiate this speed between the MAC and the PHY, we +need to have the proper comphy support enabled, to make sure we can +safely advertise 2.5G and 1G in BaseT and be able to switch between both +corresponding PHY interface modes. This is now possible since comphy +support was added to this driver. + +This commit adds the 2500BaseT mode to the list of supported modes when +using 2500BaseX, and was tested on a setup with an Armada385 and a +88E2010 PHY, both with and without the comphy node in the DT. + +Signed-off-by: Maxime Chevallier +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/marvell/mvneta.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -3387,6 +3387,7 @@ static void mvneta_validate(struct net_d + phylink_set(mask, 1000baseX_Full); + } + if (pp->comphy || state->interface == PHY_INTERFACE_MODE_2500BASEX) { ++ phylink_set(mask, 2500baseT_Full); + phylink_set(mask, 2500baseX_Full); + } + diff --git a/target/linux/mvebu/patches-4.19/538-phy-add-QSGMII-and-PCIE-modes.patch b/target/linux/mvebu/patches-4.19/538-phy-add-QSGMII-and-PCIE-modes.patch new file mode 100644 index 0000000000..b759b9fb25 --- /dev/null +++ b/target/linux/mvebu/patches-4.19/538-phy-add-QSGMII-and-PCIE-modes.patch @@ -0,0 +1,28 @@ +From c2a90025ad09d830c8d8ae69f485eac6aaaa2472 Mon Sep 17 00:00:00 2001 +From: Quentin Schulz +Date: Thu, 4 Oct 2018 14:22:03 +0200 +Subject: [PATCH] phy: add QSGMII and PCIE modes + +Prepare for upcoming phys that'll handle QSGMII or PCIe. + +Reviewed-by: Florian Fainelli +Signed-off-by: Quentin Schulz +Signed-off-by: David S. Miller +--- + include/linux/phy/phy.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/linux/phy/phy.h ++++ b/include/linux/phy/phy.h +@@ -37,9 +37,11 @@ enum phy_mode { + PHY_MODE_USB_OTG, + PHY_MODE_SGMII, + PHY_MODE_2500SGMII, ++ PHY_MODE_QSGMII, + PHY_MODE_10GKR, + PHY_MODE_UFS_HS_A, + PHY_MODE_UFS_HS_B, ++ PHY_MODE_PCIE, + }; + + /** diff --git a/target/linux/mvebu/patches-4.19/539-phy-core-add-PHY_MODE_ETHERNET.patch b/target/linux/mvebu/patches-4.19/539-phy-core-add-PHY_MODE_ETHERNET.patch new file mode 100644 index 0000000000..68fecadce8 --- /dev/null +++ b/target/linux/mvebu/patches-4.19/539-phy-core-add-PHY_MODE_ETHERNET.patch @@ -0,0 +1,24 @@ +From 2af8caeee47846a84bc96abc3a72f7c991153040 Mon Sep 17 00:00:00 2001 +From: Grygorii Strashko +Date: Mon, 19 Nov 2018 19:24:21 -0600 +Subject: [PATCH] phy: core: add PHY_MODE_ETHERNET + +Add new PHY's mode to be used by Ethernet PHY interface drivers or +multipurpose PHYs like serdes. It will be reused in further changes. + +Signed-off-by: Grygorii Strashko +Signed-off-by: Kishon Vijay Abraham I +--- + include/linux/phy/phy.h | 1 + + 1 file changed, 1 insertion(+) + +--- a/include/linux/phy/phy.h ++++ b/include/linux/phy/phy.h +@@ -42,6 +42,7 @@ enum phy_mode { + PHY_MODE_UFS_HS_A, + PHY_MODE_UFS_HS_B, + PHY_MODE_PCIE, ++ PHY_MODE_ETHERNET, + }; + + /** diff --git a/target/linux/mvebu/patches-4.19/540-phy-fix-build-breakage-add-PHY_MODE_SATA.patch b/target/linux/mvebu/patches-4.19/540-phy-fix-build-breakage-add-PHY_MODE_SATA.patch new file mode 100644 index 0000000000..83908af19e --- /dev/null +++ b/target/linux/mvebu/patches-4.19/540-phy-fix-build-breakage-add-PHY_MODE_SATA.patch @@ -0,0 +1,45 @@ +From e1706720408e72fb883f6b151c2b3b23d8e7e5b2 Mon Sep 17 00:00:00 2001 +From: John Hubbard +Date: Sat, 12 Jan 2019 17:29:09 -0800 +Subject: [PATCH] phy: fix build breakage: add PHY_MODE_SATA + +Commit 49e54187ae0b ("ata: libahci_platform: comply to PHY framework") uses +the PHY_MODE_SATA, but that enum had not yet been added. This caused a +build failure for me, with today's linux.git. + +Also, there is a potentially conflicting (mis-named) PHY_MODE_SATA, hiding +in the Marvell Berlin SATA PHY driver. + +Fix the build by: + + 1) Renaming Marvell's defined value to a more scoped name, + in order to avoid any potential conflicts: PHY_BERLIN_MODE_SATA. + + 2) Adding the missing enum, which was going to be added anyway as part + of [1]. + +[1] https://lkml.kernel.org/r/20190108163124.6409-3-miquel.raynal@bootlin.com + +Fixes: 49e54187ae0b ("ata: libahci_platform: comply to PHY framework") + +Signed-off-by: John Hubbard +Acked-by: Jens Axboe +Acked-by: Olof Johansson +Cc: Grzegorz Jaszczyk +Cc: Miquel Raynal +Cc: Hans de Goede +Signed-off-by: Linus Torvalds +--- + include/linux/phy/phy.h | 1 + + 1 file changed, 1 insertion(+) + +--- a/include/linux/phy/phy.h ++++ b/include/linux/phy/phy.h +@@ -43,6 +43,7 @@ enum phy_mode { + PHY_MODE_UFS_HS_B, + PHY_MODE_PCIE, + PHY_MODE_ETHERNET, ++ PHY_MODE_SATA + }; + + /** diff --git a/target/linux/mvebu/patches-4.19/541-phy-core-rework-phy_set_mode-to-accept-phy-mode-and-.patch b/target/linux/mvebu/patches-4.19/541-phy-core-rework-phy_set_mode-to-accept-phy-mode-and-.patch new file mode 100644 index 0000000000..e02f203912 --- /dev/null +++ b/target/linux/mvebu/patches-4.19/541-phy-core-rework-phy_set_mode-to-accept-phy-mode-and-.patch @@ -0,0 +1,134 @@ +From 79a5a18aa9d1062205cdcfa183d4cd5241d1b8da Mon Sep 17 00:00:00 2001 +From: Grygorii Strashko +Date: Mon, 19 Nov 2018 19:24:20 -0600 +Subject: [PATCH] phy: core: rework phy_set_mode to accept phy mode and submode + +Currently the attempt to add support for Ethernet interface mode PHY +(MII/GMII/RGMII) will lead to the necessity of extending enum phy_mode and +duplicate there values from phy_interface_t enum (or introduce more PHY +callbacks) [1]. Both approaches are ineffective and would lead to fast +bloating of enum phy_mode or struct phy_ops in the process of adding more +PHYs for different subsystems which will make them unmaintainable. + +As discussed in [1] the solution could be to introduce dual level PHYs mode +configuration - PHY mode and PHY submode. The PHY mode will define generic +PHY type (subsystem - PCIE/ETHERNET/USB_) while the PHY submode - subsystem +specific interface mode. The last is usually already defined in +corresponding subsystem headers (phy_interface_t for Ethernet, enum +usb_device_speed for USB). + +This patch is cumulative change which refactors PHY framework code to +support dual level PHYs mode configuration - PHY mode and PHY submode. It +extends .set_mode() callback to support additional parameter "int submode" +and converts all corresponding PHY drivers to support new .set_mode() +callback declaration. +The new extended PHY API + int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode) +is introduced to support dual level PHYs mode configuration and existing +phy_set_mode() API is converted to macros, so PHY framework consumers do +not need to be changed (~21 matches). + +[1] http://lkml.kernel.org/r/d63588f6-9ab0-848a-5ad4-8073143bd95d@ti.com +Signed-off-by: Grygorii Strashko +Signed-off-by: Kishon Vijay Abraham I +--- + drivers/phy/allwinner/phy-sun4i-usb.c | 3 ++- + drivers/phy/amlogic/phy-meson-gxl-usb2.c | 5 +++-- + drivers/phy/amlogic/phy-meson-gxl-usb3.c | 5 +++-- + drivers/phy/marvell/phy-mvebu-cp110-comphy.c | 3 ++- + drivers/phy/mediatek/phy-mtk-tphy.c | 2 +- + drivers/phy/mediatek/phy-mtk-xsphy.c | 2 +- + drivers/phy/mscc/phy-ocelot-serdes.c | 2 +- + drivers/phy/phy-core.c | 6 +++--- + drivers/phy/qualcomm/phy-qcom-qmp.c | 3 ++- + drivers/phy/qualcomm/phy-qcom-qusb2.c | 3 ++- + drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c | 3 ++- + drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c | 3 ++- + drivers/phy/qualcomm/phy-qcom-usb-hs.c | 3 ++- + drivers/phy/ti/phy-da8xx-usb.c | 3 ++- + drivers/phy/ti/phy-tusb1210.c | 2 +- + include/linux/phy/phy.h | 13 ++++++++++--- + 16 files changed, 39 insertions(+), 22 deletions(-) + +--- a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c ++++ b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c +@@ -512,7 +512,8 @@ static int mvebu_comphy_power_on(struct + return ret; + } + +-static int mvebu_comphy_set_mode(struct phy *phy, enum phy_mode mode) ++static int mvebu_comphy_set_mode(struct phy *phy, ++ enum phy_mode mode, int submode) + { + struct mvebu_comphy_lane *lane = phy_get_drvdata(phy); + +--- a/drivers/phy/phy-core.c ++++ b/drivers/phy/phy-core.c +@@ -360,7 +360,7 @@ int phy_power_off(struct phy *phy) + } + EXPORT_SYMBOL_GPL(phy_power_off); + +-int phy_set_mode(struct phy *phy, enum phy_mode mode) ++int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode) + { + int ret; + +@@ -368,14 +368,14 @@ int phy_set_mode(struct phy *phy, enum p + return 0; + + mutex_lock(&phy->mutex); +- ret = phy->ops->set_mode(phy, mode); ++ ret = phy->ops->set_mode(phy, mode, submode); + if (!ret) + phy->attrs.mode = mode; + mutex_unlock(&phy->mutex); + + return ret; + } +-EXPORT_SYMBOL_GPL(phy_set_mode); ++EXPORT_SYMBOL_GPL(phy_set_mode_ext); + + int phy_reset(struct phy *phy) + { +--- a/include/linux/phy/phy.h ++++ b/include/linux/phy/phy.h +@@ -62,7 +62,7 @@ struct phy_ops { + int (*exit)(struct phy *phy); + int (*power_on)(struct phy *phy); + int (*power_off)(struct phy *phy); +- int (*set_mode)(struct phy *phy, enum phy_mode mode); ++ int (*set_mode)(struct phy *phy, enum phy_mode mode, int submode); + int (*reset)(struct phy *phy); + int (*calibrate)(struct phy *phy); + struct module *owner; +@@ -166,7 +166,10 @@ int phy_init(struct phy *phy); + int phy_exit(struct phy *phy); + int phy_power_on(struct phy *phy); + int phy_power_off(struct phy *phy); +-int phy_set_mode(struct phy *phy, enum phy_mode mode); ++int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode); ++#define phy_set_mode(phy, mode) \ ++ phy_set_mode_ext(phy, mode, 0) ++ + static inline enum phy_mode phy_get_mode(struct phy *phy) + { + return phy->attrs.mode; +@@ -280,13 +283,17 @@ static inline int phy_power_off(struct p + return -ENOSYS; + } + +-static inline int phy_set_mode(struct phy *phy, enum phy_mode mode) ++static inline int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, ++ int submode) + { + if (!phy) + return 0; + return -ENOSYS; + } + ++#define phy_set_mode(phy, mode) \ ++ phy_set_mode_ext(phy, mode, 0) ++ + static inline enum phy_mode phy_get_mode(struct phy *phy) + { + return PHY_MODE_INVALID; diff --git a/target/linux/mvebu/patches-4.19/542-phy-add-A3700-COMPHY-support.patch b/target/linux/mvebu/patches-4.19/542-phy-add-A3700-COMPHY-support.patch new file mode 100644 index 0000000000..0964da03a8 --- /dev/null +++ b/target/linux/mvebu/patches-4.19/542-phy-add-A3700-COMPHY-support.patch @@ -0,0 +1,381 @@ +From 9695375a3f4a604406f2e61f2b735eca1de931ed Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 8 Jan 2019 17:31:20 +0100 +Subject: [PATCH] phy: add A3700 COMPHY support + +Add a driver to support COMPHY, a hardware block providing shared +serdes PHYs on Marvell Armada 3700. This driver uses SMC calls and +rely on having an up-to-date firmware. + +SATA, PCie and USB3 host mode have been tested successfully with an +ESPRESSObin. (HS)SGMII mode cannot be tested with this platform. + +Evan worked on the original driver structure and Grzegorz on the SMC +calls rework. The structure of this driver has been copied from +Antoine Tenart work on CP110 COMPHY driver. + +Signed-off-by: Miquel Raynal +Co-developed-by: Evan Wang +Signed-off-by: Evan Wang +Co-developed-by: Grzegorz Jaszczyk +Signed-off-by: Grzegorz Jaszczyk +Signed-off-by: Kishon Vijay Abraham I +--- + drivers/phy/marvell/Kconfig | 12 + + drivers/phy/marvell/Makefile | 1 + + drivers/phy/marvell/phy-mvebu-a3700-comphy.c | 318 +++++++++++++++++++++++++++ + 3 files changed, 331 insertions(+) + create mode 100644 drivers/phy/marvell/phy-mvebu-a3700-comphy.c + +--- a/drivers/phy/marvell/Kconfig ++++ b/drivers/phy/marvell/Kconfig +@@ -21,6 +21,18 @@ config PHY_BERLIN_USB + help + Enable this to support the USB PHY on Marvell Berlin SoCs. + ++config PHY_MVEBU_A3700_COMPHY ++ tristate "Marvell A3700 comphy driver" ++ depends on ARCH_MVEBU || COMPILE_TEST ++ depends on OF ++ depends on HAVE_ARM_SMCCC ++ default y ++ select GENERIC_PHY ++ help ++ This driver allows to control the comphy, a hardware block providing ++ shared serdes PHYs on Marvell Armada 3700. Its serdes lanes can be ++ used by various controllers: Ethernet, SATA, USB3, PCIe. ++ + config PHY_MVEBU_CP110_COMPHY + tristate "Marvell CP110 comphy driver" + depends on ARCH_MVEBU || COMPILE_TEST +--- a/drivers/phy/marvell/Makefile ++++ b/drivers/phy/marvell/Makefile +@@ -2,6 +2,7 @@ + obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o + obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o + obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o ++obj-$(CONFIG_PHY_MVEBU_A3700_COMPHY) += phy-mvebu-a3700-comphy.o + obj-$(CONFIG_PHY_MVEBU_CP110_COMPHY) += phy-mvebu-cp110-comphy.o + obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o + obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o +--- /dev/null ++++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c +@@ -0,0 +1,318 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2018 Marvell ++ * ++ * Authors: ++ * Evan Wang ++ * Miquèl Raynal ++ * ++ * Structure inspired from phy-mvebu-cp110-comphy.c written by Antoine Tenart. ++ * SMC call initial support done by Grzegorz Jaszczyk. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MVEBU_A3700_COMPHY_LANES 3 ++#define MVEBU_A3700_COMPHY_PORTS 2 ++ ++/* COMPHY Fast SMC function identifiers */ ++#define COMPHY_SIP_POWER_ON 0x82000001 ++#define COMPHY_SIP_POWER_OFF 0x82000002 ++#define COMPHY_SIP_PLL_LOCK 0x82000003 ++ ++#define COMPHY_FW_MODE_SATA 0x1 ++#define COMPHY_FW_MODE_SGMII 0x2 ++#define COMPHY_FW_MODE_HS_SGMII 0x3 ++#define COMPHY_FW_MODE_USB3H 0x4 ++#define COMPHY_FW_MODE_USB3D 0x5 ++#define COMPHY_FW_MODE_PCIE 0x6 ++#define COMPHY_FW_MODE_RXAUI 0x7 ++#define COMPHY_FW_MODE_XFI 0x8 ++#define COMPHY_FW_MODE_SFI 0x9 ++#define COMPHY_FW_MODE_USB3 0xa ++ ++#define COMPHY_FW_SPEED_1_25G 0 /* SGMII 1G */ ++#define COMPHY_FW_SPEED_2_5G 1 ++#define COMPHY_FW_SPEED_3_125G 2 /* SGMII 2.5G */ ++#define COMPHY_FW_SPEED_5G 3 ++#define COMPHY_FW_SPEED_5_15625G 4 /* XFI 5G */ ++#define COMPHY_FW_SPEED_6G 5 ++#define COMPHY_FW_SPEED_10_3125G 6 /* XFI 10G */ ++#define COMPHY_FW_SPEED_MAX 0x3F ++ ++#define COMPHY_FW_MODE(mode) ((mode) << 12) ++#define COMPHY_FW_NET(mode, idx, speed) (COMPHY_FW_MODE(mode) | \ ++ ((idx) << 8) | \ ++ ((speed) << 2)) ++#define COMPHY_FW_PCIE(mode, idx, speed, width) (COMPHY_FW_NET(mode, idx, speed) | \ ++ ((width) << 18)) ++ ++struct mvebu_a3700_comphy_conf { ++ unsigned int lane; ++ enum phy_mode mode; ++ int submode; ++ unsigned int port; ++ u32 fw_mode; ++}; ++ ++#define MVEBU_A3700_COMPHY_CONF(_lane, _mode, _smode, _port, _fw) \ ++ { \ ++ .lane = _lane, \ ++ .mode = _mode, \ ++ .submode = _smode, \ ++ .port = _port, \ ++ .fw_mode = _fw, \ ++ } ++ ++#define MVEBU_A3700_COMPHY_CONF_GEN(_lane, _mode, _port, _fw) \ ++ MVEBU_A3700_COMPHY_CONF(_lane, _mode, PHY_INTERFACE_MODE_NA, _port, _fw) ++ ++#define MVEBU_A3700_COMPHY_CONF_ETH(_lane, _smode, _port, _fw) \ ++ MVEBU_A3700_COMPHY_CONF(_lane, PHY_MODE_ETHERNET, _smode, _port, _fw) ++ ++static const struct mvebu_a3700_comphy_conf mvebu_a3700_comphy_modes[] = { ++ /* lane 0 */ ++ MVEBU_A3700_COMPHY_CONF_GEN(0, PHY_MODE_USB_HOST_SS, 0, ++ COMPHY_FW_MODE_USB3H), ++ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_SGMII, 1, ++ COMPHY_FW_MODE_SGMII), ++ MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_2500BASEX, 1, ++ COMPHY_FW_MODE_HS_SGMII), ++ /* lane 1 */ ++ MVEBU_A3700_COMPHY_CONF_GEN(1, PHY_MODE_PCIE, 0, ++ COMPHY_FW_MODE_PCIE), ++ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII, 0, ++ COMPHY_FW_MODE_SGMII), ++ MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_2500BASEX, 0, ++ COMPHY_FW_MODE_HS_SGMII), ++ /* lane 2 */ ++ MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_SATA, 0, ++ COMPHY_FW_MODE_SATA), ++ MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_USB_HOST_SS, 0, ++ COMPHY_FW_MODE_USB3H), ++}; ++ ++struct mvebu_a3700_comphy_lane { ++ struct device *dev; ++ unsigned int id; ++ enum phy_mode mode; ++ int submode; ++ int port; ++}; ++ ++static int mvebu_a3700_comphy_smc(unsigned long function, unsigned long lane, ++ unsigned long mode) ++{ ++ struct arm_smccc_res res; ++ ++ arm_smccc_smc(function, lane, mode, 0, 0, 0, 0, 0, &res); ++ ++ return res.a0; ++} ++ ++static int mvebu_a3700_comphy_get_fw_mode(int lane, int port, ++ enum phy_mode mode, ++ int submode) ++{ ++ int i, n = ARRAY_SIZE(mvebu_a3700_comphy_modes); ++ ++ /* Unused PHY mux value is 0x0 */ ++ if (mode == PHY_MODE_INVALID) ++ return -EINVAL; ++ ++ for (i = 0; i < n; i++) { ++ if (mvebu_a3700_comphy_modes[i].lane == lane && ++ mvebu_a3700_comphy_modes[i].port == port && ++ mvebu_a3700_comphy_modes[i].mode == mode && ++ mvebu_a3700_comphy_modes[i].submode == submode) ++ break; ++ } ++ ++ if (i == n) ++ return -EINVAL; ++ ++ return mvebu_a3700_comphy_modes[i].fw_mode; ++} ++ ++static int mvebu_a3700_comphy_set_mode(struct phy *phy, enum phy_mode mode, ++ int submode) ++{ ++ struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); ++ int fw_mode; ++ ++ if (submode == PHY_INTERFACE_MODE_1000BASEX) ++ submode = PHY_INTERFACE_MODE_SGMII; ++ ++ fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, lane->port, mode, ++ submode); ++ if (fw_mode < 0) { ++ dev_err(lane->dev, "invalid COMPHY mode\n"); ++ return fw_mode; ++ } ++ ++ /* Just remember the mode, ->power_on() will do the real setup */ ++ lane->mode = mode; ++ lane->submode = submode; ++ ++ return 0; ++} ++ ++static int mvebu_a3700_comphy_power_on(struct phy *phy) ++{ ++ struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); ++ u32 fw_param; ++ int fw_mode; ++ ++ fw_mode = mvebu_a3700_comphy_get_fw_mode(lane->id, lane->port, ++ lane->mode, lane->submode); ++ if (fw_mode < 0) { ++ dev_err(lane->dev, "invalid COMPHY mode\n"); ++ return fw_mode; ++ } ++ ++ switch (lane->mode) { ++ case PHY_MODE_USB_HOST_SS: ++ dev_dbg(lane->dev, "set lane %d to USB3 host mode\n", lane->id); ++ fw_param = COMPHY_FW_MODE(fw_mode); ++ break; ++ case PHY_MODE_SATA: ++ dev_dbg(lane->dev, "set lane %d to SATA mode\n", lane->id); ++ fw_param = COMPHY_FW_MODE(fw_mode); ++ break; ++ case PHY_MODE_ETHERNET: ++ switch (lane->submode) { ++ case PHY_INTERFACE_MODE_SGMII: ++ dev_dbg(lane->dev, "set lane %d to SGMII mode\n", ++ lane->id); ++ fw_param = COMPHY_FW_NET(fw_mode, lane->port, ++ COMPHY_FW_SPEED_1_25G); ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ dev_dbg(lane->dev, "set lane %d to HS SGMII mode\n", ++ lane->id); ++ fw_param = COMPHY_FW_NET(fw_mode, lane->port, ++ COMPHY_FW_SPEED_3_125G); ++ break; ++ default: ++ dev_err(lane->dev, "unsupported PHY submode (%d)\n", ++ lane->submode); ++ return -ENOTSUPP; ++ } ++ break; ++ case PHY_MODE_PCIE: ++ dev_dbg(lane->dev, "set lane %d to PCIe mode\n", lane->id); ++ fw_param = COMPHY_FW_PCIE(fw_mode, lane->port, ++ COMPHY_FW_SPEED_5G, ++ phy->attrs.bus_width); ++ break; ++ default: ++ dev_err(lane->dev, "unsupported PHY mode (%d)\n", lane->mode); ++ return -ENOTSUPP; ++ } ++ ++ return mvebu_a3700_comphy_smc(COMPHY_SIP_POWER_ON, lane->id, fw_param); ++} ++ ++static int mvebu_a3700_comphy_power_off(struct phy *phy) ++{ ++ struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy); ++ ++ return mvebu_a3700_comphy_smc(COMPHY_SIP_POWER_OFF, lane->id, 0); ++} ++ ++static const struct phy_ops mvebu_a3700_comphy_ops = { ++ .power_on = mvebu_a3700_comphy_power_on, ++ .power_off = mvebu_a3700_comphy_power_off, ++ .set_mode = mvebu_a3700_comphy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static struct phy *mvebu_a3700_comphy_xlate(struct device *dev, ++ struct of_phandle_args *args) ++{ ++ struct mvebu_a3700_comphy_lane *lane; ++ struct phy *phy; ++ ++ if (WARN_ON(args->args[0] >= MVEBU_A3700_COMPHY_PORTS)) ++ return ERR_PTR(-EINVAL); ++ ++ phy = of_phy_simple_xlate(dev, args); ++ if (IS_ERR(phy)) ++ return phy; ++ ++ lane = phy_get_drvdata(phy); ++ lane->port = args->args[0]; ++ ++ return phy; ++} ++ ++static int mvebu_a3700_comphy_probe(struct platform_device *pdev) ++{ ++ struct phy_provider *provider; ++ struct device_node *child; ++ ++ for_each_available_child_of_node(pdev->dev.of_node, child) { ++ struct mvebu_a3700_comphy_lane *lane; ++ struct phy *phy; ++ int ret; ++ u32 lane_id; ++ ++ ret = of_property_read_u32(child, "reg", &lane_id); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "missing 'reg' property (%d)\n", ++ ret); ++ continue; ++ } ++ ++ if (lane_id >= MVEBU_A3700_COMPHY_LANES) { ++ dev_err(&pdev->dev, "invalid 'reg' property\n"); ++ continue; ++ } ++ ++ lane = devm_kzalloc(&pdev->dev, sizeof(*lane), GFP_KERNEL); ++ if (!lane) ++ return -ENOMEM; ++ ++ phy = devm_phy_create(&pdev->dev, child, ++ &mvebu_a3700_comphy_ops); ++ if (IS_ERR(phy)) ++ return PTR_ERR(phy); ++ ++ lane->dev = &pdev->dev; ++ lane->mode = PHY_MODE_INVALID; ++ lane->submode = PHY_INTERFACE_MODE_NA; ++ lane->id = lane_id; ++ lane->port = -1; ++ phy_set_drvdata(phy, lane); ++ } ++ ++ provider = devm_of_phy_provider_register(&pdev->dev, ++ mvebu_a3700_comphy_xlate); ++ return PTR_ERR_OR_ZERO(provider); ++} ++ ++static const struct of_device_id mvebu_a3700_comphy_of_match_table[] = { ++ { .compatible = "marvell,comphy-a3700" }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, mvebu_a3700_comphy_of_match_table); ++ ++static struct platform_driver mvebu_a3700_comphy_driver = { ++ .probe = mvebu_a3700_comphy_probe, ++ .driver = { ++ .name = "mvebu-a3700-comphy", ++ .of_match_table = mvebu_a3700_comphy_of_match_table, ++ }, ++}; ++module_platform_driver(mvebu_a3700_comphy_driver); ++ ++MODULE_AUTHOR("Miquèl Raynal "); ++MODULE_DESCRIPTION("Common PHY driver for A3700"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/mvebu/patches-4.19/543-arm64-dts-marvell-armada-37xx-declare-the-COMPHY.patch b/target/linux/mvebu/patches-4.19/543-arm64-dts-marvell-armada-37xx-declare-the-COMPHY.patch new file mode 100644 index 0000000000..393f823794 --- /dev/null +++ b/target/linux/mvebu/patches-4.19/543-arm64-dts-marvell-armada-37xx-declare-the-COMPHY.patch @@ -0,0 +1,58 @@ +From 2ef303f0fe44feee4a3ca8bd62fca86c105927d2 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Tue, 8 Jan 2019 17:31:24 +0100 +Subject: [PATCH] arm64: dts: marvell: armada-37xx: declare the COMPHY + node + +Describe the A3700 COMPHY node. It has three PHYs that can be +configured as follow: +* PCIe or GbE +* USB3 or GbE +* SATA or USB3 +Each of them has its own memory area. + +Suggested-by: Grzegorz Jaszczyk +Signed-off-by: Miquel Raynal +Signed-off-by: Gregory CLEMENT +--- + arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 29 ++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi ++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +@@ -235,6 +235,35 @@ + reg = <0x14000 0x60>; + }; + ++ comphy: phy@18300 { ++ compatible = "marvell,comphy-a3700"; ++ reg = <0x18300 0x300>, ++ <0x1F000 0x400>, ++ <0x5C000 0x400>, ++ <0xe0178 0x8>; ++ reg-names = "comphy", ++ "lane1_pcie_gbe", ++ "lane0_usb3_gbe", ++ "lane2_sata_usb3"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ comphy0: phy@0 { ++ reg = <0>; ++ #phy-cells = <1>; ++ }; ++ ++ comphy1: phy@1 { ++ reg = <1>; ++ #phy-cells = <1>; ++ }; ++ ++ comphy2: phy@2 { ++ reg = <2>; ++ #phy-cells = <1>; ++ }; ++ }; ++ + pinctrl_sb: pinctrl@18800 { + compatible = "marvell,armada3710-sb-pinctrl", + "syscon", "simple-mfd";