mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2026-05-05 18:06:12 +02:00
realtek: pcs: replace various SerDes range checks
The whole driver often does some range checks of the SerDes ID to restrict some functionality to a group of SerDes. However, having these open-coded checks everywhere is rather confusing because it's not obvious what it actually means. Luckily, those checks give a good picture of what SerDes types we have: - 5G: RTL838x, RTL839x (0-7, 10, 11), RTL930x (0, 1) - 10G: RTL839x (8, 9, 12, 13), RTL930x (2-9), RTL931x (2-13) - unknown: RTL930x (10, 11), RTL931x (0, 1) Add a new enum and field in rtpcs_serdes for the type of a SerDes we have. This is filled during SerDes probe, making use of the stub implementations for that hook.. All SerDes ID range checks related to this are replaced with corresponding checks of the SerDes type. Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com> Link: https://github.com/openwrt/openwrt/pull/22941 Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
parent
c32e90a396
commit
f95dbe3575
@ -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;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user