[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250904154402.300032-11-vladimir.oltean@nxp.com>
Date: Thu, 4 Sep 2025 18:43:58 +0300
From: Vladimir Oltean <vladimir.oltean@....com>
To: linux-phy@...ts.infradead.org
Cc: Ioana Ciornei <ioana.ciornei@....com>,
Vinod Koul <vkoul@...nel.org>,
Kishon Vijay Abraham I <kishon@...nel.org>,
linux-kernel@...r.kernel.org
Subject: [PATCH phy 10/14] phy: lynx-28g: add support for 25GBASER
From: Ioana Ciornei <ioana.ciornei@....com>
Add support for 25GBASE-R in the Lynx 28G SerDes PHY driver.
This mainly means being able to determine if a PLL is able to support
the new interface type, to determine at probe time if a lane is
configured from the Reset Configuration Word (RCW) with this interface
type and to be able to reconfigure a lane.
Signed-off-by: Ioana Ciornei <ioana.ciornei@....com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@....com>
---
drivers/phy/freescale/phy-fsl-lynx-28g.c | 83 +++++++++++++++++++++++-
1 file changed, 82 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/freescale/phy-fsl-lynx-28g.c b/drivers/phy/freescale/phy-fsl-lynx-28g.c
index 1a8751e79898..08553ffe273f 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-28g.c
+++ b/drivers/phy/freescale/phy-fsl-lynx-28g.c
@@ -57,6 +57,7 @@
#define PLLnCR1_FRATE_5G_10GVCO 0x0
#define PLLnCR1_FRATE_5G_25GVCO 0x10
#define PLLnCR1_FRATE_10G_20GVCO 0x6
+#define PLLnCR1_FRATE_12G_25GVCO 0x16
/* Per SerDes lane registers */
/* Lane a General Control Register */
@@ -64,9 +65,11 @@
#define LNaGCR0_PROTO_SEL GENMASK(7, 3)
#define LNaGCR0_PROTO_SEL_SGMII 0x1
#define LNaGCR0_PROTO_SEL_XFI 0xa
+#define LNaGCR0_PROTO_SEL_25G 0x1a
#define LNaGCR0_IF_WIDTH GENMASK(2, 0)
#define LNaGCR0_IF_WIDTH_10_BIT 0x0
#define LNaGCR0_IF_WIDTH_20_BIT 0x2
+#define LNaGCR0_IF_WIDTH_40_BIT 0x4
/* Lane a Tx Reset Control Register */
#define LNaTRSTCTL(lane) (0x800 + (lane) * 0x100 + 0x20)
@@ -83,6 +86,7 @@
#define LNaTGCR0_N_RATE_FULL 0x0
#define LNaTGCR0_N_RATE_HALF 0x1
#define LNaTGCR0_N_RATE_QUARTER 0x2
+#define LNaTGCR0_N_RATE_DOUBLE 0x3
#define LNaTECR0(lane) (0x800 + (lane) * 0x100 + 0x30)
#define LNaTECR0_EQ_TYPE GENMASK(30, 28)
@@ -112,6 +116,7 @@
#define LNaRGCR0_N_RATE_FULL 0x0
#define LNaRGCR0_N_RATE_HALF 0x1
#define LNaRGCR0_N_RATE_QUARTER 0x2
+#define LNaRGCR0_N_RATE_DOUBLE 0x3
#define LNaRGCR1(lane) (0x800 + (lane) * 0x100 + 0x48)
#define LNaRGCR1_RX_ORD_ELECIDLE BIT(31)
@@ -270,6 +275,7 @@ enum lynx_lane_mode {
LANE_MODE_1000BASEX_SGMII,
LANE_MODE_10GBASER,
LANE_MODE_USXGMII,
+ LANE_MODE_25GBASER,
LANE_MODE_MAX,
};
@@ -408,6 +414,41 @@ static const struct lynx_28g_proto_conf lynx_28g_proto_conf[LANE_MODE_MAX] = {
.ttlcr0 = LNaTTLCR0_TTL_SLO_PM_BYP |
LNaTTLCR0_DATA_IN_SSC,
},
+ [LANE_MODE_25GBASER] = {
+ .proto_sel = LNaGCR0_PROTO_SEL_25G,
+ .if_width = LNaGCR0_IF_WIDTH_40_BIT,
+ .teq_type = EQ_TYPE_3TAP,
+ .sgn_preq = 1,
+ .ratio_preq = 2,
+ .sgn_post1q = 1,
+ .ratio_post1q = 7,
+ .amp_red = 0,
+ .adpt_eq = 48,
+ .enter_idle_flt_sel = 0,
+ .exit_idle_flt_sel = 0,
+ .data_lost_th_sel = 0,
+ .gk2ovd = 0,
+ .gk3ovd = 0,
+ .gk4ovd = 5,
+ .gk2ovd_en = 0,
+ .gk3ovd_en = 0,
+ .gk4ovd_en = 1,
+ .eq_offset_ovd = 0x1f,
+ .eq_offset_ovd_en = 0,
+ .eq_offset_rng_dbl = 1,
+ .eq_blw_sel = 1,
+ .eq_boost = 2,
+ .spare_in = 3,
+ .smp_autoz_d1r = 2,
+ .smp_autoz_eg1r = 2,
+ .rccr0 = LNaRCCR0_CAL_EN |
+ LNaRCCR0_CAL_DC3_DIS |
+ LNaRCCR0_CAL_DC2_DIS |
+ LNaRCCR0_CAL_DC1_DIS |
+ LNaRCCR0_CAL_DC0_DIS,
+ .ttlcr0 = LNaTTLCR0_DATA_IN_SSC |
+ FIELD_PREP_CONST(LNaTTLCR0_CDR_MIN_SMP_ON, 1),
+ },
};
struct lynx_pccr {
@@ -481,6 +522,8 @@ static const char *lynx_lane_mode_str(enum lynx_lane_mode lane_mode)
return "10GBase-R";
case LANE_MODE_USXGMII:
return "USXGMII";
+ case LANE_MODE_25GBASER:
+ return "25GBase-R";
default:
return "unknown";
}
@@ -496,6 +539,8 @@ static enum lynx_lane_mode phy_interface_to_lane_mode(phy_interface_t intf)
return LANE_MODE_10GBASER;
case PHY_INTERFACE_MODE_USXGMII:
return LANE_MODE_USXGMII;
+ case PHY_INTERFACE_MODE_25GBASER:
+ return LANE_MODE_25GBASER;
default:
return LANE_MODE_UNKNOWN;
}
@@ -576,6 +621,20 @@ static void lynx_28g_lane_set_nrate(struct lynx_28g_lane *lane,
break;
}
break;
+ case PLLnCR1_FRATE_12G_25GVCO:
+ switch (lane_mode) {
+ case LANE_MODE_25GBASER:
+ lynx_28g_lane_rmw(lane, LNaTGCR0,
+ FIELD_PREP(LNaTGCR0_N_RATE, LNaTGCR0_N_RATE_DOUBLE),
+ LNaTGCR0_N_RATE);
+ lynx_28g_lane_rmw(lane, LNaRGCR0,
+ FIELD_PREP(LNaRGCR0_N_RATE, LNaRGCR0_N_RATE_DOUBLE),
+ LNaRGCR0_N_RATE);
+ break;
+ default:
+ break;
+ }
+ break;
default:
break;
}
@@ -653,6 +712,11 @@ static int lynx_28g_power_on(struct phy *phy)
return 0;
}
+static int lynx_28g_e25g_pcvt(int lane)
+{
+ return 7 - lane;
+}
+
static int lynx_28g_get_pccr(enum lynx_lane_mode lane_mode, int lane,
struct lynx_pccr *pccr)
{
@@ -668,6 +732,11 @@ static int lynx_28g_get_pccr(enum lynx_lane_mode lane_mode, int lane,
pccr->width = 4;
pccr->shift = SXGMII_CFG(lane);
break;
+ case LANE_MODE_25GBASER:
+ pccr->offset = PCCD;
+ pccr->width = 4;
+ pccr->shift = E25G_CFG(lynx_28g_e25g_pcvt(lane));
+ break;
default:
return -EOPNOTSUPP;
}
@@ -683,6 +752,8 @@ static int lynx_28g_get_pcvt_offset(int lane, enum lynx_lane_mode lane_mode)
case LANE_MODE_USXGMII:
case LANE_MODE_10GBASER:
return SXGMIIaCR0(lane);
+ case LANE_MODE_25GBASER:
+ return E25GaCR0(lynx_28g_e25g_pcvt(lane));
default:
return -EOPNOTSUPP;
}
@@ -924,6 +995,9 @@ static int lynx_28g_lane_enable_pcvt(struct lynx_28g_lane *lane,
case LANE_MODE_USXGMII:
val |= PCCC_SXGMIIn_CFG;
break;
+ case LANE_MODE_25GBASER:
+ val |= PCCD_E25Gn_CFG;
+ break;
default:
break;
}
@@ -1050,8 +1124,12 @@ static void lynx_28g_pll_read_configuration(struct lynx_28g_priv *priv)
__set_bit(LANE_MODE_10GBASER, pll->supported);
__set_bit(LANE_MODE_USXGMII, pll->supported);
break;
+ case PLLnCR1_FRATE_12G_25GVCO:
+ /* 12.890625GHz clock net */
+ __set_bit(LANE_MODE_25GBASER, pll->supported);
+ break;
default:
- /* 6GHz, 12.890625GHz, 8GHz */
+ /* 6GHz, 8GHz */
break;
}
}
@@ -1108,6 +1186,9 @@ static void lynx_28g_lane_read_configuration(struct lynx_28g_lane *lane)
else
lane->mode = LANE_MODE_USXGMII;
break;
+ case LNaPSS_TYPE_25G:
+ lane->mode = LANE_MODE_25GBASER;
+ break;
default:
lane->mode = LANE_MODE_UNKNOWN;
}
--
2.34.1
Powered by blists - more mailing lists