diff options
Diffstat (limited to 'target/linux/generic')
4 files changed, 375 insertions, 0 deletions
diff --git a/target/linux/generic/backport-5.15/778-v5.18-01-net-phy-at803x-add-fiber-support.patch b/target/linux/generic/backport-5.15/778-v5.18-01-net-phy-at803x-add-fiber-support.patch new file mode 100644 index 0000000000..7cb21ed00d --- /dev/null +++ b/target/linux/generic/backport-5.15/778-v5.18-01-net-phy-at803x-add-fiber-support.patch @@ -0,0 +1,193 @@ +From 3265f421887847db9ae2c01a00645e33608556d8 Mon Sep 17 00:00:00 2001 +From: Robert Hancock <robert.hancock@calian.com> +Date: Tue, 25 Jan 2022 10:54:09 -0600 +Subject: [PATCH] net: phy: at803x: add fiber support + +Previously this driver always forced the copper page to be selected, +however for AR8031 in 100Base-FX or 1000Base-X modes, the fiber page +needs to be selected. Set the appropriate mode based on the hardware +mode_cfg strap selection. + +Enable the appropriate interrupt bits to detect fiber-side link up +or down events. + +Update config_aneg and read_status methods to use the appropriate +Clause 37 calls when fiber mode is in use. + +Signed-off-by: Robert Hancock <robert.hancock@calian.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/phy/at803x.c | 76 +++++++++++++++++++++++++++++++++++----- + 1 file changed, 67 insertions(+), 9 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -48,6 +48,8 @@ + #define AT803X_INTR_ENABLE_PAGE_RECEIVED BIT(12) + #define AT803X_INTR_ENABLE_LINK_FAIL BIT(11) + #define AT803X_INTR_ENABLE_LINK_SUCCESS BIT(10) ++#define AT803X_INTR_ENABLE_LINK_FAIL_BX BIT(8) ++#define AT803X_INTR_ENABLE_LINK_SUCCESS_BX BIT(7) + #define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE BIT(5) + #define AT803X_INTR_ENABLE_POLARITY_CHANGED BIT(1) + #define AT803X_INTR_ENABLE_WOL BIT(0) +@@ -82,6 +84,17 @@ + + #define AT803X_MODE_CFG_MASK 0x0F + #define AT803X_MODE_CFG_SGMII 0x01 ++#define AT803X_MODE_CFG_BASET_RGMII 0x00 ++#define AT803X_MODE_CFG_BASET_SGMII 0x01 ++#define AT803X_MODE_CFG_BX1000_RGMII_50OHM 0x02 ++#define AT803X_MODE_CFG_BX1000_RGMII_75OHM 0x03 ++#define AT803X_MODE_CFG_BX1000_CONV_50OHM 0x04 ++#define AT803X_MODE_CFG_BX1000_CONV_75OHM 0x05 ++#define AT803X_MODE_CFG_FX100_RGMII_50OHM 0x06 ++#define AT803X_MODE_CFG_FX100_CONV_50OHM 0x07 ++#define AT803X_MODE_CFG_RGMII_AUTO_MDET 0x0B ++#define AT803X_MODE_CFG_FX100_RGMII_75OHM 0x0E ++#define AT803X_MODE_CFG_FX100_CONV_75OHM 0x0F + + #define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/ + #define AT803X_PSSR_MR_AN_COMPLETE 0x0200 +@@ -199,6 +212,8 @@ struct at803x_priv { + u16 clk_25m_mask; + u8 smarteee_lpi_tw_1g; + u8 smarteee_lpi_tw_100m; ++ bool is_fiber; ++ bool is_1000basex; + struct regulator_dev *vddio_rdev; + struct regulator_dev *vddh_rdev; + struct regulator *vddio; +@@ -674,7 +689,33 @@ static int at803x_probe(struct phy_devic + return ret; + } + ++ if (phydev->drv->phy_id == ATH8031_PHY_ID) { ++ int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); ++ int mode_cfg; ++ ++ if (ccr < 0) ++ goto err; ++ mode_cfg = ccr & AT803X_MODE_CFG_MASK; ++ ++ switch (mode_cfg) { ++ case AT803X_MODE_CFG_BX1000_RGMII_50OHM: ++ case AT803X_MODE_CFG_BX1000_RGMII_75OHM: ++ priv->is_1000basex = true; ++ fallthrough; ++ case AT803X_MODE_CFG_FX100_RGMII_50OHM: ++ case AT803X_MODE_CFG_FX100_RGMII_75OHM: ++ priv->is_fiber = true; ++ break; ++ } ++ } ++ + return 0; ++ ++err: ++ if (priv->vddio) ++ regulator_disable(priv->vddio); ++ ++ return ret; + } + + static void at803x_remove(struct phy_device *phydev) +@@ -687,6 +728,7 @@ static void at803x_remove(struct phy_dev + + static int at803x_get_features(struct phy_device *phydev) + { ++ struct at803x_priv *priv = phydev->priv; + int err; + + err = genphy_read_abilities(phydev); +@@ -704,12 +746,13 @@ static int at803x_get_features(struct ph + * As a result of that, ESTATUS_1000_XFULL is set + * to 1 even when operating in copper TP mode. + * +- * Remove this mode from the supported link modes, +- * as this driver currently only supports copper +- * operation. ++ * Remove this mode from the supported link modes ++ * when not operating in 1000BaseX mode. + */ +- linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, +- phydev->supported); ++ if (!priv->is_1000basex) ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, ++ phydev->supported); ++ + return 0; + } + +@@ -773,15 +816,18 @@ static int at8031_pll_config(struct phy_ + + static int at803x_config_init(struct phy_device *phydev) + { ++ struct at803x_priv *priv = phydev->priv; + int ret; + + if (phydev->drv->phy_id == ATH8031_PHY_ID) { + /* Some bootloaders leave the fiber page selected. +- * Switch to the copper page, as otherwise we read +- * the PHY capabilities from the fiber side. ++ * Switch to the appropriate page (fiber or copper), as otherwise we ++ * read the PHY capabilities from the wrong page. + */ + phy_lock_mdio_bus(phydev); +- ret = at803x_write_page(phydev, AT803X_PAGE_COPPER); ++ ret = at803x_write_page(phydev, ++ priv->is_fiber ? AT803X_PAGE_FIBER : ++ AT803X_PAGE_COPPER); + phy_unlock_mdio_bus(phydev); + if (ret) + return ret; +@@ -840,6 +886,7 @@ static int at803x_ack_interrupt(struct p + + static int at803x_config_intr(struct phy_device *phydev) + { ++ struct at803x_priv *priv = phydev->priv; + int err; + int value; + +@@ -856,6 +903,10 @@ static int at803x_config_intr(struct phy + value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED; + value |= AT803X_INTR_ENABLE_LINK_FAIL; + value |= AT803X_INTR_ENABLE_LINK_SUCCESS; ++ if (priv->is_fiber) { ++ value |= AT803X_INTR_ENABLE_LINK_FAIL_BX; ++ value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX; ++ } + + err = phy_write(phydev, AT803X_INTR_ENABLE, value); + } else { +@@ -923,8 +974,12 @@ static void at803x_link_change_notify(st + + static int at803x_read_status(struct phy_device *phydev) + { ++ struct at803x_priv *priv = phydev->priv; + int ss, err, old_link = phydev->link; + ++ if (priv->is_1000basex) ++ return genphy_c37_read_status(phydev); ++ + /* Update the link, but return if there was an error */ + err = genphy_update_link(phydev); + if (err) +@@ -1023,6 +1078,7 @@ static int at803x_config_mdix(struct phy + + static int at803x_config_aneg(struct phy_device *phydev) + { ++ struct at803x_priv *priv = phydev->priv; + int ret; + + ret = at803x_config_mdix(phydev, phydev->mdix_ctrl); +@@ -1039,6 +1095,9 @@ static int at803x_config_aneg(struct phy + return ret; + } + ++ if (priv->is_1000basex) ++ return genphy_c37_config_aneg(phydev); ++ + return genphy_config_aneg(phydev); + } + diff --git a/target/linux/generic/backport-5.15/778-v5.18-02-net-phy-at803x-support-downstream-SFP-cage.patch b/target/linux/generic/backport-5.15/778-v5.18-02-net-phy-at803x-support-downstream-SFP-cage.patch new file mode 100644 index 0000000000..8393cb32e8 --- /dev/null +++ b/target/linux/generic/backport-5.15/778-v5.18-02-net-phy-at803x-support-downstream-SFP-cage.patch @@ -0,0 +1,95 @@ +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; diff --git a/target/linux/generic/backport-5.15/778-v5.18-03-net-phy-at803x-fix-NULL-pointer-dereference-on-AR9331-PHY.patch b/target/linux/generic/backport-5.15/778-v5.18-03-net-phy-at803x-fix-NULL-pointer-dereference-on-AR9331-PHY.patch new file mode 100644 index 0000000000..de8951db10 --- /dev/null +++ b/target/linux/generic/backport-5.15/778-v5.18-03-net-phy-at803x-fix-NULL-pointer-dereference-on-AR9331-PHY.patch @@ -0,0 +1,56 @@ +From 9926de7315be3d606cc011a305ad9adb9e8e14c9 Mon Sep 17 00:00:00 2001 +From: Oleksij Rempel <o.rempel@pengutronix.de> +Date: Sat, 18 Jun 2022 14:23:33 +0200 +Subject: [PATCH] net: phy: at803x: fix NULL pointer dereference on AR9331 PHY + +Latest kernel will explode on the PHY interrupt config, since it depends +now on allocated priv. So, run probe to allocate priv to fix it. + + ar9331_switch ethernet.1:10 lan0 (uninitialized): PHY [!ahb!ethernet@1a000000!mdio!switch@10:00] driver [Qualcomm Atheros AR9331 built-in PHY] (irq=13) + CPU 0 Unable to handle kernel paging request at virtual address 0000000a, epc == 8050e8a8, ra == 80504b34 + ... + Call Trace: + [<8050e8a8>] at803x_config_intr+0x5c/0xd0 + [<80504b34>] phy_request_interrupt+0xa8/0xd0 + [<8050289c>] phylink_bringup_phy+0x2d8/0x3ac + [<80502b68>] phylink_fwnode_phy_connect+0x118/0x130 + [<8074d8ec>] dsa_slave_create+0x270/0x420 + [<80743b04>] dsa_port_setup+0x12c/0x148 + [<8074580c>] dsa_register_switch+0xaf0/0xcc0 + [<80511344>] ar9331_sw_probe+0x370/0x388 + [<8050cb78>] mdio_probe+0x44/0x70 + [<804df300>] really_probe+0x200/0x424 + [<804df7b4>] __driver_probe_device+0x290/0x298 + [<804df810>] driver_probe_device+0x54/0xe4 + [<804dfd50>] __device_attach_driver+0xe4/0x130 + [<804dcb00>] bus_for_each_drv+0xb4/0xd8 + [<804dfac4>] __device_attach+0x104/0x1a4 + [<804ddd24>] bus_probe_device+0x48/0xc4 + [<804deb44>] deferred_probe_work_func+0xf0/0x10c + [<800a0ffc>] process_one_work+0x314/0x4d4 + [<800a17fc>] worker_thread+0x2a4/0x354 + [<800a9a54>] kthread+0x134/0x13c + [<8006306c>] ret_from_kernel_thread+0x14/0x1c + +Same Issue would affect some other PHYs (QCA8081, QCA9561), so fix it +too. + +Fixes: 3265f4218878 ("net: phy: at803x: add fiber support") +Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> +Reviewed-by: Andrew Lunn <andrew@lunn.ch> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/phy/at803x.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1594,6 +1594,8 @@ static struct phy_driver at803x_driver[] + /* ATHEROS AR9331 */ + PHY_ID_MATCH_EXACT(ATH9331_PHY_ID), + .name = "Qualcomm Atheros AR9331 built-in PHY", ++ .probe = at803x_probe, ++ .remove = at803x_remove, + .suspend = at803x_suspend, + .resume = at803x_resume, + .flags = PHY_POLL_CABLE_TEST, diff --git a/target/linux/generic/backport-5.15/778-v5.18-04-net-phy-at803x-fix-error-return-code-in-at803x_probe.patch b/target/linux/generic/backport-5.15/778-v5.18-04-net-phy-at803x-fix-error-return-code-in-at803x_probe.patch new file mode 100644 index 0000000000..cdae5b4ca4 --- /dev/null +++ b/target/linux/generic/backport-5.15/778-v5.18-04-net-phy-at803x-fix-error-return-code-in-at803x_probe.patch @@ -0,0 +1,31 @@ +From 1f0dd412e34e177621769866bef347f0b22364df Mon Sep 17 00:00:00 2001 +From: Wei Yongjun <weiyongjun1@huawei.com> +Date: Fri, 18 Nov 2022 10:36:35 +0000 +Subject: [PATCH] net: phy: at803x: fix error return code in at803x_probe() + +Fix to return a negative error code from the ccr read error handling +case instead of 0, as done elsewhere in this function. + +Fixes: 3265f4218878 ("net: phy: at803x: add fiber support") +Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com> +Reviewed-by: Andrew Lunn <andrew@lunn.ch> +Link: https://lore.kernel.org/r/20221118103635.254256-1-weiyongjun@huaweicloud.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +--- + drivers/net/phy/at803x.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -749,8 +749,10 @@ static int at803x_probe(struct phy_devic + int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); + int mode_cfg; + +- if (ccr < 0) ++ if (ccr < 0) { ++ ret = ccr; + goto err; ++ } + mode_cfg = ccr & AT803X_MODE_CFG_MASK; + + switch (mode_cfg) { |