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 02cd0b70f3..c8429b4596 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 @@ -109,6 +109,12 @@ #define RTPCS_931X_SDS_MAIN_AMP_MASK GENMASK(9, 5) #define RTPCS_931X_SDS_POST_AMP_MASK GENMASK(14, 10) +enum rtpcs_sds_type { + RTPCS_SDS_TYPE_UNKNOWN, + RTPCS_SDS_TYPE_5G, + RTPCS_SDS_TYPE_10G, +}; + enum rtpcs_sds_mode { RTPCS_SDS_MODE_OFF = 0, @@ -201,6 +207,7 @@ struct rtpcs_serdes { struct rtpcs_ctrl *ctrl; const struct rtpcs_sds_ops *ops; const struct rtpcs_sds_regs *regs; + enum rtpcs_sds_type type; enum rtpcs_sds_mode hw_mode; u8 id; u8 num_of_links; @@ -838,6 +845,7 @@ static int rtpcs_838x_sds_patch(struct rtpcs_serdes *sds, static int rtpcs_838x_sds_probe(struct rtpcs_serdes *sds) { + sds->type = RTPCS_SDS_TYPE_5G; return 0; } @@ -902,17 +910,14 @@ static void rtpcs_839x_sds_reset(struct rtpcs_serdes *sds) struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); struct rtpcs_serdes *odd_sds = rtpcs_sds_get_odd(sds); - bool is_10g_sds = (sds->id == 8 || sds->id == 9 || sds->id == 12 || - sds->id == 13); - /* FIXME: The reset sequence seems to break some of the 5G SerDes * though the SDK is calling it for all SerDes during init. Until * this is solved, skip reset. */ - if (!is_10g_sds) + if (sds->type == RTPCS_SDS_TYPE_5G) return; - if (is_10g_sds) { + if (sds->type == RTPCS_SDS_TYPE_10G) { rtpcs_sds_write_bits(odd_sds, 0x2f, 0x1d, 3, 0, 0x5); msleep(500); rtpcs_sds_write_bits(odd_sds, 0x2f, 0x1d, 3, 0, 0xf); @@ -977,14 +982,19 @@ static int rtpcs_839x_sds_probe(struct rtpcs_serdes *sds) { bool is_even = sds->id % 2 == 0; + if (sds->id == 8 || sds->id == 9 || sds->id == 12 || sds->id == 13) + sds->type = RTPCS_SDS_TYPE_10G; + else + sds->type = RTPCS_SDS_TYPE_5G; + /* * This function is quite "mystic". It has been taken over from the vendor SDK function * rtl839x_serdes_patch_init(). There is not much documentation about it but one could * lookup the fields from the field headers. The 5G SerDes seem to work out of the box * so only setup the 10G SerDes for now. */ - if (sds->id != 8 && sds->id != 9 && sds->id != 12 && sds->id != 13) - return; + if (sds->type == RTPCS_SDS_TYPE_5G) + return 0; /* Part 1: register setup */ rtpcs_sds_write(sds, 0x2e, 0x0, 0x5800); @@ -1086,10 +1096,13 @@ static int rtpcs_839x_sds_probe(struct rtpcs_serdes *sds) rtpcs_sds_write_bits(sds, 0x2e, 0x13, 9, 9, 0x0000); rtpcs_sds_write_bits(sds, 0x2e, 0x13, 3, 0, 0x0008); rtpcs_sds_write_bits(sds, 0x2e, 0x13, 8, 5, 0x0008); + + return 0; } static int rtpcs_839x_init(struct rtpcs_ctrl *ctrl) { + /* reset all SerDes once after patching has been applied before */ for (int sds_id = 0; sds_id < ctrl->cfg->serdes_count; sds_id++) rtpcs_839x_sds_reset(&ctrl->serdes[sds_id]); @@ -1105,7 +1118,7 @@ static int rtpcs_839x_setup_serdes(struct rtpcs_serdes *sds, * at startup for QSGMII. Thus, connected PHYs should work out * of the box. */ - if (sds->id != 8 && sds->id != 9 && sds->id != 12 && sds->id != 13) + if (sds->type == RTPCS_SDS_TYPE_5G) return 0; ret = rtpcs_839x_sds_set_mode(sds, hw_mode); @@ -1458,7 +1471,7 @@ static int __rtpcs_930x_sds_get_usxgmii_submode(struct rtpcs_serdes *sds) u8 sds_id = sds->id; int submode, ret; - if (sds_id < 2 || sds_id > 9) { + if (sds->type != RTPCS_SDS_TYPE_10G) { pr_err("%s: SerDes %u doesn't support USXGMII submode\n", __func__, sds_id); return -ENOTSUPP; } @@ -1475,7 +1488,7 @@ static int __rtpcs_930x_sds_set_usxgmii_submode(struct rtpcs_serdes *sds, u32 su { u8 sds_id = sds->id; - if (sds_id < 2 || sds_id > 9) { + if (sds->type != RTPCS_SDS_TYPE_10G) { pr_err("%s: SerDes %u doesn't support USXGMII submode\n", __func__, sds_id); return -ENOTSUPP; } @@ -2844,7 +2857,7 @@ static int rtpcs_930x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sd apply_fn = is_xsgmii ? rtpcs_sds_apply_config_xsg : rtpcs_sds_apply_config; if (hw_mode == RTPCS_SDS_MODE_QSGMII) { - if (sds->id >= 2) + if (sds->type != RTPCS_SDS_TYPE_5G) return -ENOTSUPP; return rtpcs_sds_apply_config(sds, rtpcs_930x_sds_cfg_5g_qsgmii, @@ -3036,6 +3049,13 @@ skip_cali: static int rtpcs_930x_sds_probe(struct rtpcs_serdes *sds) { + if (sds->id < 2) + sds->type = RTPCS_SDS_TYPE_5G; + else if (sds->id <= 9) + sds->type = RTPCS_SDS_TYPE_10G; + else + sds->type = RTPCS_SDS_TYPE_UNKNOWN; + return 0; } @@ -3304,7 +3324,7 @@ static void rtpcs_931x_sds_reset(struct rtpcs_serdes *sds) static void rtpcs_931x_sds_rx_reset(struct rtpcs_serdes *sds) { - if (sds->id < 2) + if (sds->type != RTPCS_SDS_TYPE_10G) return; rtpcs_sds_write(sds, 0x2e, 0x12, 0x2740); @@ -3602,7 +3622,7 @@ static int rtpcs_931x_sds_config_tx(struct rtpcs_serdes *sds, { const struct rtpcs_sds_tx_config *tx_cfg; - if (sds->id < 2) + if (sds->type != RTPCS_SDS_TYPE_10G) return 0; switch (sds_media) { @@ -3930,6 +3950,11 @@ static int rtpcs_931x_init_mac_groups(struct rtpcs_ctrl *ctrl) static int rtpcs_931x_sds_probe(struct rtpcs_serdes *sds) { + if (sds->id >= 2) + sds->type = RTPCS_SDS_TYPE_10G; + else + sds->type = RTPCS_SDS_TYPE_UNKNOWN; + return 0; }