diff options
Diffstat (limited to 'drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c')
-rw-r--r-- | drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c index 42b0083c9193..8b7b476ed7fb 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c @@ -2,6 +2,7 @@ // Copyright (c) 2024 Hisilicon Limited. #include <linux/phy.h> +#include <linux/phy_fixed.h> #include <linux/rtnetlink.h> #include "hbg_common.h" #include "hbg_hw.h" @@ -19,6 +20,7 @@ #define HBG_MDIO_OP_INTERVAL_US (5 * 1000) #define HBG_NP_LINK_FAIL_RETRY_TIMES 5 +#define HBG_NO_PHY 0xFF static void hbg_mdio_set_command(struct hbg_mac *mac, u32 cmd) { @@ -229,6 +231,39 @@ void hbg_phy_stop(struct hbg_priv *priv) phy_stop(priv->mac.phydev); } +static void hbg_fixed_phy_uninit(void *data) +{ + fixed_phy_unregister((struct phy_device *)data); +} + +static int hbg_fixed_phy_init(struct hbg_priv *priv) +{ + struct fixed_phy_status hbg_fixed_phy_status = { + .link = 1, + .speed = SPEED_1000, + .duplex = DUPLEX_FULL, + .pause = 1, + .asym_pause = 1, + }; + struct device *dev = &priv->pdev->dev; + struct phy_device *phydev; + int ret; + + phydev = fixed_phy_register(&hbg_fixed_phy_status, NULL); + if (IS_ERR(phydev)) { + dev_err_probe(dev, PTR_ERR(phydev), + "failed to register fixed PHY device\n"); + return PTR_ERR(phydev); + } + + ret = devm_add_action_or_reset(dev, hbg_fixed_phy_uninit, phydev); + if (ret) + return ret; + + priv->mac.phydev = phydev; + return hbg_phy_connect(priv); +} + int hbg_mdio_init(struct hbg_priv *priv) { struct device *dev = &priv->pdev->dev; @@ -238,6 +273,9 @@ int hbg_mdio_init(struct hbg_priv *priv) int ret; mac->phy_addr = priv->dev_specs.phy_addr; + if (mac->phy_addr == HBG_NO_PHY) + return hbg_fixed_phy_init(priv); + mdio_bus = devm_mdiobus_alloc(dev); if (!mdio_bus) return dev_err_probe(dev, -ENOMEM, |