diff options
Diffstat (limited to 'target/linux/mvebu')
15 files changed, 1165 insertions, 0 deletions
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 <maxime.chevallier@bootlin.com> +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 <maxime.chevallier@bootlin.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + 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 <alexandre.belloni@bootlin.com> +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 <alexandre.belloni@bootlin.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + 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 <maxime.chevallier@bootlin.com> +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 <andrew@lunn.ch> +Reported-by: Russell King <linux@armlinux.org.uk> +Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + 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 <yuehaibing@huawei.com> +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 <yuehaibing@huawei.com> +Acked-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + 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 <rmk+kernel@armlinux.org.uk> +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 <rmk+kernel@armlinux.org.uk> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + 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 <linux/of_irq.h> + #include <linux/of_mdio.h> + #include <linux/of_net.h> ++#include <linux/phy/phy.h> + #include <linux/phy.h> + #include <linux/phylink.h> + #include <linux/platform_device.h> +@@ -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?= <marek.behun@nic.cz> +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 <marek.behun@nic.cz> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + 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 <maxime.chevallier@bootlin.com> +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 <maxime.chevallier@bootlin.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + 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 <quentin.schulz@bootlin.com> +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 <f.fainelli@gmail.com> +Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + 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 <grygorii.strashko@ti.com> +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 <grygorii.strashko@ti.com> +Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> +--- + 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 <jhubbard@nvidia.com> +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 <jhubbard@nvidia.com> +Acked-by: Jens Axboe <axboe@kernel.dk> +Acked-by: Olof Johansson <olof@lixom.net> +Cc: Grzegorz Jaszczyk <jaz@semihalf.com> +Cc: Miquel Raynal <miquel.raynal@bootlin.com> +Cc: Hans de Goede <hdegoede@redhat.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +--- + 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 <grygorii.strashko@ti.com> +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 <grygorii.strashko@ti.com> +Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> +--- + 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 <miquel.raynal@bootlin.com> +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 <miquel.raynal@bootlin.com> +Co-developed-by: Evan Wang <xswang@marvell.com> +Signed-off-by: Evan Wang <xswang@marvell.com> +Co-developed-by: Grzegorz Jaszczyk <jaz@semihalf.com> +Signed-off-by: Grzegorz Jaszczyk <jaz@semihalf.com> +Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> +--- + 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 <xswang@marvell.com> ++ * Miquèl Raynal <miquel.raynal@bootlin.com> ++ * ++ * Structure inspired from phy-mvebu-cp110-comphy.c written by Antoine Tenart. ++ * SMC call initial support done by Grzegorz Jaszczyk. ++ */ ++ ++#include <linux/arm-smccc.h> ++#include <linux/io.h> ++#include <linux/iopoll.h> ++#include <linux/mfd/syscon.h> ++#include <linux/module.h> ++#include <linux/phy.h> ++#include <linux/phy/phy.h> ++#include <linux/platform_device.h> ++ ++#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 <miquel.raynal@bootlin.com>"); ++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 <miquel.raynal@bootlin.com> +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 <jaz@semihalf.com> +Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> +Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com> +--- + 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"; |