Add a SD1 mode that keeps dpmac.2 as 40GE on LNA-LND and that changes the LNE-LNH 40GE port 4xXFI ports, dpmac.3-6.
Signed-off-by: Vincent Jardin <[email protected]> --- Changes in v7: - Reset only LNE-LNH, as 100g4x25g (Vladimir) Changes in v5: - sd1_reset_req() Changes in v4: - was on v3 3/5, now let's add an entry of the mode table board/nxp/lx2160a/serdes_split.c | 51 ++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/board/nxp/lx2160a/serdes_split.c b/board/nxp/lx2160a/serdes_split.c index 41208ca79ab..316d500292a 100644 --- a/board/nxp/lx2160a/serdes_split.c +++ b/board/nxp/lx2160a/serdes_split.c @@ -572,6 +572,50 @@ static int sd1_enter_2x40g(unsigned long base) return err ? err : ret; } +/* + * 1x40GE + 4x10G: dpmac.2 stays 40GE on LNA-LND, LNE-LNH become + * 4xXFI ports, dpmac.3-6. + * An XFI lane is a 40GE lane that is its own port master: + * same PROTO_SEL and width, same PLLS and rate. + * + * XFI LNmGCR0 = 0x00000052 LNmTGCR0 = 0x10000000 + * 40GE LNmGCR0 = 0x00010052 LNmTGCR0 = 0x10000000 (but its master) + * ^ PORT_LN0_B + */ +#define XFI_GCR0 0x00000052 /* as 40GE, but own port master */ +#define X10G_PCCE 0x01000000 /* E40Gb kept (lanes 0-3) */ +#define XFI_PCCC 0x88889999 /* XFI converters for lanes 4-7 */ + +static bool sd1_is_40g4x10g(unsigned long base) +{ + u32 pccc = in_le32((void __iomem *)SRDS_PCCC(base)); + u32 pcce = in_le32((void __iomem *)SRDS_PCCE(base)); + + return PCCE_E40GB_CFG(pcce) != 0 && PCCE_E40GA_CFG(pcce) == 0 && + (pccc & 0xffff) == 0x9999; +} + +static int sd1_enter_40g4x10g(unsigned long base) +{ + unsigned long lanes = SD1_LNE_LNH; + int m, ret, err; + + 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_PCCE(base), X10G_PCCE); + out_le32((void __iomem *)SRDS_PCCC(base), XFI_PCCC); + + sd1_reset_req(base, lanes); + err = sd1_reset_wait(base, lanes); + + return err ? err : ret; +} + static const struct sd1_mode sd1_modes[] = { { .name = "2x100g", @@ -592,6 +636,13 @@ static const struct sd1_mode sd1_modes[] = { .is_active = sd1_is_2x40g, .enter = sd1_enter_2x40g, }, + { + .name = "40g4x10g", + .desc = "1x 40GE + 4x 10G", + .from = "2x40g", + .is_active = sd1_is_40g4x10g, + .enter = sd1_enter_40g4x10g, + }, }; static const struct sd1_mode *sd1_mode_find(const char *name, size_t len) -- 2.43.0
