aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mvebu
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/mvebu')
-rw-r--r--target/linux/mvebu/config-4.191
-rw-r--r--target/linux/mvebu/cortexa53/config-4.191
-rw-r--r--target/linux/mvebu/patches-4.19/531-net-mvneta-Add-support-for-2500Mbps-SGMII.patch104
-rw-r--r--target/linux/mvebu/patches-4.19/532-net-mvneta-correct-typo.patch33
-rw-r--r--target/linux/mvebu/patches-4.19/533-net-mvneta-Dont-advertise-2.5G-modes.patch55
-rw-r--r--target/linux/mvebu/patches-4.19/534-net-mvneta-remove-redundant-check-for.patch30
-rw-r--r--target/linux/mvebu/patches-4.19/535-net-marvell-neta-add-comphy-support.patch159
-rw-r--r--target/linux/mvebu/patches-4.19/536-net-marvell-neta-disable-comphy-when-setting-mode.patch78
-rw-r--r--target/linux/mvebu/patches-4.19/537-net-mvneta-add-2500baset-support.patch34
-rw-r--r--target/linux/mvebu/patches-4.19/538-phy-add-QSGMII-and-PCIE-modes.patch28
-rw-r--r--target/linux/mvebu/patches-4.19/539-phy-core-add-PHY_MODE_ETHERNET.patch24
-rw-r--r--target/linux/mvebu/patches-4.19/540-phy-fix-build-breakage-add-PHY_MODE_SATA.patch45
-rw-r--r--target/linux/mvebu/patches-4.19/541-phy-core-rework-phy_set_mode-to-accept-phy-mode-and-.patch134
-rw-r--r--target/linux/mvebu/patches-4.19/542-phy-add-A3700-COMPHY-support.patch381
-rw-r--r--target/linux/mvebu/patches-4.19/543-arm64-dts-marvell-armada-37xx-declare-the-COMPHY.patch58
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";