diff options
author | Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> | 2023-08-07 09:32:30 +0900 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2023-08-08 15:31:52 -0700 |
commit | c009b903f8ccfce5844c91f005b0f152a5518526 (patch) | |
tree | d6ce7a720ee260a67674ed8a9c762caffa1c5cd0 /drivers | |
parent | f1d152eb66a30aecd19f22ff2676a7cb2584a920 (diff) | |
download | lwn-c009b903f8ccfce5844c91f005b0f152a5518526.tar.gz lwn-c009b903f8ccfce5844c91f005b0f152a5518526.zip |
net: renesas: rswitch: Add runtime speed change support
The latest SoC version can support runtime speed change. So,
add detect SoC version by using soc_device_match() and then
reconfigure the hardware of this and SerDes if needed.
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://lore.kernel.org/r/20230807003231.1552062-2-yoshihiro.shimoda.uh@renesas.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/renesas/rswitch.c | 27 | ||||
-rw-r--r-- | drivers/net/ethernet/renesas/rswitch.h | 1 |
2 files changed, 25 insertions, 3 deletions
diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c index 0ba7fb75d589..fd3668b95834 100644 --- a/drivers/net/ethernet/renesas/rswitch.c +++ b/drivers/net/ethernet/renesas/rswitch.c @@ -20,6 +20,7 @@ #include <linux/rtnetlink.h> #include <linux/slab.h> #include <linux/spinlock.h> +#include <linux/sys_soc.h> #include "rswitch.h" @@ -1243,7 +1244,6 @@ static void rswitch_adjust_link(struct net_device *ndev) struct rswitch_device *rdev = netdev_priv(ndev); struct phy_device *phydev = ndev->phydev; - /* Current hardware has a restriction not to change speed at runtime */ if (phydev->link != rdev->etha->link) { phy_print_status(phydev); if (phydev->link) @@ -1252,13 +1252,23 @@ static void rswitch_adjust_link(struct net_device *ndev) phy_power_off(rdev->serdes); rdev->etha->link = phydev->link; + + if (!rdev->priv->etha_no_runtime_change && + phydev->speed != rdev->etha->speed) { + rdev->etha->speed = phydev->speed; + + rswitch_etha_hw_init(rdev->etha, rdev->ndev->dev_addr); + phy_set_speed(rdev->serdes, rdev->etha->speed); + } } } static void rswitch_phy_remove_link_mode(struct rswitch_device *rdev, struct phy_device *phydev) { - /* Current hardware has a restriction not to change speed at runtime */ + if (!rdev->priv->etha_no_runtime_change) + return; + switch (rdev->etha->speed) { case SPEED_2500: phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Full_BIT); @@ -1347,7 +1357,8 @@ static int rswitch_ether_port_init_one(struct rswitch_device *rdev) err = rswitch_etha_hw_init(rdev->etha, rdev->ndev->dev_addr); if (err < 0) return err; - rdev->etha->operated = true; + if (rdev->priv->etha_no_runtime_change) + rdev->etha->operated = true; } err = rswitch_mii_register(rdev); @@ -1853,8 +1864,14 @@ err_ts_queue_alloc: return err; } +static const struct soc_device_attribute rswitch_soc_no_speed_change[] = { + { .soc_id = "r8a779f0", .revision = "ES1.0" }, + { /* Sentinel */ } +}; + static int renesas_eth_sw_probe(struct platform_device *pdev) { + const struct soc_device_attribute *attr; struct rswitch_private *priv; struct resource *res; int ret; @@ -1869,6 +1886,10 @@ static int renesas_eth_sw_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; + attr = soc_device_match(rswitch_soc_no_speed_change); + if (attr) + priv->etha_no_runtime_change = true; + priv->ptp_priv = rcar_gen4_ptp_alloc(pdev); if (!priv->ptp_priv) return -ENOMEM; diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h index bb9ed971a97c..54f397effbc6 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -1011,6 +1011,7 @@ struct rswitch_private { struct rswitch_etha etha[RSWITCH_NUM_PORTS]; struct rswitch_mfwd mfwd; + bool etha_no_runtime_change; bool gwca_halt; }; |