Add the SD1 mode that keeps dpmac.2 as 100GE on LNA-LND and makes LNE-LNH four XFI ports, dpmac.3-6.
Signed-off-by: Vincent Jardin <[email protected]> --- Changes in v7: - Reset only LNE-LNH, as 40g4x10g does now - Reviewed-by dropped, since the reset changed Changes in v4: - Was on v3 with 4/5, now let's add an entry of the mode table board/nxp/lx2160a/serdes_split.c | 54 ++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/board/nxp/lx2160a/serdes_split.c b/board/nxp/lx2160a/serdes_split.c index 316d500292a..d6daf4aa638 100644 --- a/board/nxp/lx2160a/serdes_split.c +++ b/board/nxp/lx2160a/serdes_split.c @@ -616,6 +616,53 @@ static int sd1_enter_40g4x10g(unsigned long base) return err ? err : ret; } +/* + * 1x100GE + 4x10G: dpmac.2 stays 100GE on LNA-LND at 25.78125 Gbaud on PLLF, + * and LNE-LNH become four XFI ports, dpmac.3-6, at 10.3125 Gbaud on PLLS. + * + * Note: it is the only mode that runs SD1 on both PLLs Slow and Fast ! + */ +#define M100G_PCCE SPLIT_PCCE /* E100Gb kept (lanes 0-3) */ + +static bool sd1_is_100g4x10g(unsigned long base) +{ + u32 pccc = in_le32((void __iomem *)SRDS_PCCC(base)); + u32 pcce = in_le32((void __iomem *)SRDS_PCCE(base)); + + return PCCE_E100GB_CFG(pcce) != 0 && PCCE_E100GA_CFG(pcce) == 0 && + (pccc & 0xffff) == 0x9999; +} + +static int sd1_enter_100g4x10g(unsigned long base) +{ + unsigned long lanes = SD1_LNE_LNH; + int m, ret, err; + + ret = sd1_plls_up(base); + if (ret) + return ret; + + /* Halt only the port that moves. */ + ret = sd1_halt_port(base, lanes); + if (ret == -EINVAL) + return ret; + + for_each_set_bit(m, &lanes, SRDS_LANES) { + out_le32((void __iomem *)SRDS_LNmGCR0(base, m), XFI_GCR0); + out_le32((void __iomem *)SRDS_LNmTGCR0(base, m), SLOW_LANE_GCR); + out_le32((void __iomem *)SRDS_LNmRGCR0(base, m), SLOW_LANE_GCR); + } + + out_le32((void __iomem *)SRDS_PCCE(base), M100G_PCCE); + out_le32((void __iomem *)SRDS_PCCC(base), XFI_PCCC); + + /* As in 40g4x10g, only the lanes that moved are reset. */ + sd1_reset_req(base, lanes); + err = sd1_reset_wait(base, lanes); + + return err ? err : ret; +} + static const struct sd1_mode sd1_modes[] = { { .name = "2x100g", @@ -643,6 +690,13 @@ static const struct sd1_mode sd1_modes[] = { .is_active = sd1_is_40g4x10g, .enter = sd1_enter_40g4x10g, }, + { + .name = "100g4x10g", + .desc = "1x 100GE + 4x 10G", + .from = "2x100g", + .is_active = sd1_is_100g4x10g, + .enter = sd1_enter_100g4x10g, + }, }; static const struct sd1_mode *sd1_mode_find(const char *name, size_t len) -- 2.43.0
