forked from Openwrt/openwrt
e1242fc339
A patch was added in kernel 5.4 to support the fiber operation of AR8033 with ramips devices. In kernel 5.18 similar enhancements were added to the kernel. Those patches are required for other fiber based devices but when added, build fails for ramips targets. This commit removes the ramips patch and adds the kernel 5.18 ones. Signed-off-by: Daniel Kestrel <kestrel1974@t-online.de> [ split commit,refresh patch and improve commit message ] Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
96 lines
3.2 KiB
Diff
96 lines
3.2 KiB
Diff
From dc4d5fcc5d365c9f70ea3f5c09bdf70e988fad50 Mon Sep 17 00:00:00 2001
|
|
From: Robert Hancock <robert.hancock@calian.com>
|
|
Date: Tue, 25 Jan 2022 10:54:10 -0600
|
|
Subject: [PATCH] net: phy: at803x: Support downstream SFP cage
|
|
|
|
Add support for downstream SFP cages for AR8031 and AR8033. This is
|
|
primarily intended for fiber modules or direct-attach cables, however
|
|
copper modules which work in 1000Base-X mode may also function. Such
|
|
modules are allowed with a warning.
|
|
|
|
Signed-off-by: Robert Hancock <robert.hancock@calian.com>
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
---
|
|
drivers/net/phy/at803x.c | 56 ++++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 56 insertions(+)
|
|
|
|
--- a/drivers/net/phy/at803x.c
|
|
+++ b/drivers/net/phy/at803x.c
|
|
@@ -19,6 +19,8 @@
|
|
#include <linux/regulator/of_regulator.h>
|
|
#include <linux/regulator/driver.h>
|
|
#include <linux/regulator/consumer.h>
|
|
+#include <linux/phylink.h>
|
|
+#include <linux/sfp.h>
|
|
#include <dt-bindings/net/qca-ar803x.h>
|
|
|
|
#define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10
|
|
@@ -555,6 +557,55 @@ static int at8031_register_regulators(st
|
|
return 0;
|
|
}
|
|
|
|
+static int at803x_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
|
|
+{
|
|
+ struct phy_device *phydev = upstream;
|
|
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support);
|
|
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support);
|
|
+ phy_interface_t iface;
|
|
+
|
|
+ linkmode_zero(phy_support);
|
|
+ phylink_set(phy_support, 1000baseX_Full);
|
|
+ phylink_set(phy_support, 1000baseT_Full);
|
|
+ phylink_set(phy_support, Autoneg);
|
|
+ phylink_set(phy_support, Pause);
|
|
+ phylink_set(phy_support, Asym_Pause);
|
|
+
|
|
+ linkmode_zero(sfp_support);
|
|
+ sfp_parse_support(phydev->sfp_bus, id, sfp_support);
|
|
+ /* Some modules support 10G modes as well as others we support.
|
|
+ * Mask out non-supported modes so the correct interface is picked.
|
|
+ */
|
|
+ linkmode_and(sfp_support, phy_support, sfp_support);
|
|
+
|
|
+ if (linkmode_empty(sfp_support)) {
|
|
+ dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ iface = sfp_select_interface(phydev->sfp_bus, sfp_support);
|
|
+
|
|
+ /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes
|
|
+ * interface for use with SFP modules.
|
|
+ * However, some copper modules detected as having a preferred SGMII
|
|
+ * interface do default to and function in 1000Base-X mode, so just
|
|
+ * print a warning and allow such modules, as they may have some chance
|
|
+ * of working.
|
|
+ */
|
|
+ if (iface == PHY_INTERFACE_MODE_SGMII)
|
|
+ dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n");
|
|
+ else if (iface != PHY_INTERFACE_MODE_1000BASEX)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct sfp_upstream_ops at803x_sfp_ops = {
|
|
+ .attach = phy_sfp_attach,
|
|
+ .detach = phy_sfp_detach,
|
|
+ .module_insert = at803x_sfp_insert,
|
|
+};
|
|
+
|
|
static int at803x_parse_dt(struct phy_device *phydev)
|
|
{
|
|
struct device_node *node = phydev->mdio.dev.of_node;
|
|
@@ -662,6 +713,11 @@ static int at803x_parse_dt(struct phy_de
|
|
phydev_err(phydev, "failed to get VDDIO regulator\n");
|
|
return PTR_ERR(priv->vddio);
|
|
}
|
|
+
|
|
+ /* Only AR8031/8033 support 1000Base-X for SFP modules */
|
|
+ ret = phy_sfp_probe(phydev, &at803x_sfp_ops);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
}
|
|
|
|
return 0;
|