]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: dsa: mxl-gsw1xx: Support R(G)MII slew rate configuration
authorAlexander Sverdlin <alexander.sverdlin@siemens.com>
Wed, 14 Jan 2026 10:45:04 +0000 (11:45 +0100)
committerJakub Kicinski <kuba@kernel.org>
Mon, 19 Jan 2026 18:08:24 +0000 (10:08 -0800)
Support newly introduced maxlinear,slew-rate-txc and
maxlinear,slew-rate-txd device tree properties to configure R(G)MII
interface pins' slew rate. It might be used to reduce the radiated
emissions.

Reviewed-by: Daniel Golle <daniel@makrotopia.org>
Tested-by: Daniel Golle <daniel@makrotopia.org>
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@siemens.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Link: https://patch.msgid.link/20260114104509.618984-3-alexander.sverdlin@siemens.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/dsa/lantiq/lantiq_gswip.h
drivers/net/dsa/lantiq/lantiq_gswip_common.c
drivers/net/dsa/lantiq/mxl-gsw1xx.c
drivers/net/dsa/lantiq/mxl-gsw1xx.h

index 2e0f2afbadbbc9967808e512b0f41d87d88bec70..8fc4c7cc5283a86037524903d77948fc49e52ae2 100644 (file)
@@ -263,6 +263,7 @@ struct gswip_hw_info {
                                 struct phylink_config *config);
        struct phylink_pcs *(*mac_select_pcs)(struct phylink_config *config,
                                              phy_interface_t interface);
+       int (*port_setup)(struct dsa_switch *ds, int port);
 };
 
 struct gswip_gphy_fw {
index e790f2ef758846fe0f179feecb2495d44df04313..17a61e445f00f2bed6de30afe4449733c9d481c7 100644 (file)
@@ -425,6 +425,12 @@ static int gswip_port_setup(struct dsa_switch *ds, int port)
        struct gswip_priv *priv = ds->priv;
        int err;
 
+       if (priv->hw_info->port_setup) {
+               err = priv->hw_info->port_setup(ds, port);
+               if (err)
+                       return err;
+       }
+
        if (!dsa_is_cpu_port(ds, port)) {
                err = gswip_add_single_port_br(priv, port, true);
                if (err)
index f8ff8a604bf5352d8c6bcc1d9d5a5f953e6c0d15..6afc7539fefbebe5225466288490708efc108ec0 100644 (file)
@@ -559,6 +559,43 @@ static struct phylink_pcs *gsw1xx_phylink_mac_select_pcs(struct phylink_config *
        }
 }
 
+static int gsw1xx_rmii_slew_rate(const struct device_node *np, struct gsw1xx_priv *priv,
+                                const char *prop, u16 mask)
+{
+       u32 rate;
+       int ret;
+
+       ret = of_property_read_u32(np, prop, &rate);
+       /* Optional property */
+       if (ret == -EINVAL)
+               return 0;
+       if (ret < 0 || rate > 1) {
+               dev_err(&priv->mdio_dev->dev, "Invalid %s value\n", prop);
+               return (ret < 0) ? ret : -EINVAL;
+       }
+
+       return regmap_update_bits(priv->shell, GSW1XX_SHELL_RGMII_SLEW_CFG, mask, mask * rate);
+}
+
+static int gsw1xx_port_setup(struct dsa_switch *ds, int port)
+{
+       struct dsa_port *dp = dsa_to_port(ds, port);
+       struct device_node *np = dp->dn;
+       struct gsw1xx_priv *gsw1xx_priv;
+       struct gswip_priv *gswip_priv;
+
+       if (dp->index != GSW1XX_MII_PORT)
+               return 0;
+
+       gswip_priv = ds->priv;
+       gsw1xx_priv = container_of(gswip_priv, struct gsw1xx_priv, gswip);
+
+       return gsw1xx_rmii_slew_rate(np, gsw1xx_priv,
+                                    "maxlinear,slew-rate-txc", RGMII_SLEW_CFG_DRV_TXC) ?:
+              gsw1xx_rmii_slew_rate(np, gsw1xx_priv,
+                                    "maxlinear,slew-rate-txd", RGMII_SLEW_CFG_DRV_TXD);
+}
+
 static struct regmap *gsw1xx_regmap_init(struct gsw1xx_priv *priv,
                                         const char *name,
                                         unsigned int reg_base,
@@ -707,6 +744,7 @@ static const struct gswip_hw_info gsw12x_data = {
        .mac_select_pcs         = gsw1xx_phylink_mac_select_pcs,
        .phylink_get_caps       = &gsw1xx_phylink_get_caps,
        .supports_2500m         = true,
+       .port_setup             = gsw1xx_port_setup,
        .pce_microcode          = &gsw1xx_pce_microcode,
        .pce_microcode_size     = ARRAY_SIZE(gsw1xx_pce_microcode),
        .tag_protocol           = DSA_TAG_PROTO_MXL_GSW1XX,
@@ -720,6 +758,7 @@ static const struct gswip_hw_info gsw140_data = {
        .mac_select_pcs         = gsw1xx_phylink_mac_select_pcs,
        .phylink_get_caps       = &gsw1xx_phylink_get_caps,
        .supports_2500m         = true,
+       .port_setup             = gsw1xx_port_setup,
        .pce_microcode          = &gsw1xx_pce_microcode,
        .pce_microcode_size     = ARRAY_SIZE(gsw1xx_pce_microcode),
        .tag_protocol           = DSA_TAG_PROTO_MXL_GSW1XX,
@@ -732,6 +771,7 @@ static const struct gswip_hw_info gsw141_data = {
        .mii_port_reg_offset    = -GSW1XX_MII_PORT,
        .mac_select_pcs         = gsw1xx_phylink_mac_select_pcs,
        .phylink_get_caps       = gsw1xx_phylink_get_caps,
+       .port_setup             = gsw1xx_port_setup,
        .pce_microcode          = &gsw1xx_pce_microcode,
        .pce_microcode_size     = ARRAY_SIZE(gsw1xx_pce_microcode),
        .tag_protocol           = DSA_TAG_PROTO_MXL_GSW1XX,
index 38e03c048a26cc56e88919c2b43b322a2f6c5d5a..8c0298b2b766303840c1bab3afa8944657641e53 100644 (file)
 #define   GSW1XX_RST_REQ_SGMII_SHELL           BIT(5)
 /* RGMII PAD Slew Control Register */
 #define  GSW1XX_SHELL_RGMII_SLEW_CFG           0x78
+#define   RGMII_SLEW_CFG_DRV_TXC               BIT(2)
+#define   RGMII_SLEW_CFG_DRV_TXD               BIT(3)
 #define   RGMII_SLEW_CFG_RX_2_5_V              BIT(4)
 #define   RGMII_SLEW_CFG_TX_2_5_V              BIT(5)