From ac916653b82826f1500f499720c1740dba3142a5 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Mon, 20 Apr 2026 19:20:49 +0000 Subject: [PATCH] realtek: pcs: add regmap-based MAC mode infrastructure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All four Realtek PCS variants (RTL838x, RTL839x, RTL930x, RTL931x) configure the SerDes MAC mode by writing a register field whose layout varies per variant — different base registers, different bit positions, and in some cases per-SerDes packing that isn't arithmetically regular. Add the common infrastructure to express this uniformly: - per-SerDes regmap_field pointers in a new 'swcore_regs' anonymous struct on rtpcs_serdes: mac_mode, mac_mode_force (931x only, nullable) and usxgmii_submode (930x only, nullable). - a per-variant mode-value table pointer (sds_hw_mode_vals) on rtpcs_config, keyed by enum rtpcs_sds_mode. Values are s16 with -1 as the "unsupported" sentinel — u8 with 0 would collide with RTL839x's OFF value (0x0). - a generic rtpcs_sds_set_mac_mode() that looks up the value for the requested mode and writes it via the regmap_field. Variant-specific extras (post-write delay, force bit, companion register writes, USXGMII submode handling) will be added in per-variant wrappers in the following commits. Signed-off-by: Jonas Jelonek Link: https://github.com/openwrt/openwrt/pull/23040 Signed-off-by: Robert Marko --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 2c6fa8bf2c..60b914ab33 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -138,6 +138,8 @@ enum rtpcs_sds_mode { RTPCS_SDS_MODE_USXGMII_5GSXGMII, RTPCS_SDS_MODE_USXGMII_5GDXGMII, RTPCS_SDS_MODE_USXGMII_2_5GSXGMII, + + RTPCS_SDS_MODE_MAX, }; enum rtpcs_sds_media { @@ -213,6 +215,12 @@ struct rtpcs_serdes { const struct rtpcs_sds_ops *ops; const struct rtpcs_sds_regs *regs; enum rtpcs_sds_type type; + struct { + struct regmap_field *mac_mode; + struct regmap_field *mac_mode_force; /* nullable, 931x only */ + struct regmap_field *usxgmii_submode; /* nullable, 93xx only */ + } swcore_regs; + enum rtpcs_sds_mode hw_mode; u8 id; u8 num_of_links; @@ -252,6 +260,8 @@ struct rtpcs_config { const struct phylink_pcs_ops *pcs_ops; const struct rtpcs_sds_ops *sds_ops; const struct rtpcs_sds_regs *sds_regs; + const s16 *sds_hw_mode_vals; /* enum rtpcs_sds_mode, -1 = unsupported */ + int (*init)(struct rtpcs_ctrl *ctrl); int (*sds_probe)(struct rtpcs_serdes *sds); int (*setup_serdes)(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode); @@ -599,6 +609,43 @@ static int rtpcs_sds_apply_config_xsg(struct rtpcs_serdes *sds, return 0; } +/* + * Allocate a regmap_field on the SoC-side register map for this SerDes and + * store the resulting pointer in *dst. Convenience helper for per-SerDes + * register fields computed from the SerDes ID. Taking reg/lsb/msb as + * integer arguments (rather than a struct reg_field) keeps callers free of + * either local reg_field declarations or compound-literal casts, since + * REG_FIELD() is a brace-initializer and not a usable expression. + */ +static int rtpcs_sds_alloc_field(struct rtpcs_serdes *sds, struct regmap_field **dst, + u32 reg, u8 lsb, u8 msb) +{ + struct reg_field rf = REG_FIELD(reg, lsb, msb); + + *dst = devm_regmap_field_alloc(sds->ctrl->dev, sds->ctrl->map, rf); + return PTR_ERR_OR_ZERO(*dst); +} + +/* + * Write the SerDes MAC mode register. This is the common minimum shared by + * all variants. Variant-specific extras (force bit, companion registers, + * USXGMII submode, post-write delay) live in per-variant wrappers. + */ +static int rtpcs_sds_set_mac_mode(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) +{ + const struct rtpcs_config *cfg = sds->ctrl->cfg; + int val; + + if (hw_mode >= RTPCS_SDS_MODE_MAX) + return -EINVAL; + + val = cfg->sds_hw_mode_vals[hw_mode]; + if (val < 0) + return -EOPNOTSUPP; + + return regmap_field_write(sds->swcore_regs.mac_mode, val); +} + /* Variant-specific functions */ /* RTL838X */