Skip to content

Commit 7c7bdd8

Browse files
jonasjelonekhauke
authored andcommitted
realtek: pcs: rtl93xx: slightly improve CMU config
Do some slight improvements to the generic CMU configuration for RTL93xx. This covers several points: - update comments to the current reality - add fast path to avoid issues and unneeded calls - use cached mode value instead of register read Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com> Link: openwrt/openwrt#22198 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
1 parent eccb5c6 commit 7c7bdd8

1 file changed

Lines changed: 35 additions & 24 deletions

File tree

target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,7 +1161,6 @@ static int rtpcs_93xx_sds_set_pll_config(struct rtpcs_serdes *sds, enum rtpcs_sd
11611161
* LC PLL. As it is unclear if disabling PLLs has any positive or negative effect,
11621162
* always activate both.
11631163
*/
1164-
11651164
ret = rtpcs_sds_write_bits(even_sds, 0x20, 0x12, 3, 0, 0xf);
11661165
if (ret < 0)
11671166
return ret;
@@ -1186,47 +1185,56 @@ static int rtpcs_93xx_sds_config_cmu(struct rtpcs_serdes *sds, enum rtpcs_sds_mo
11861185
int ret;
11871186

11881187
/*
1189-
* A SerDes pair on the RTL930x is driven by two PLLs. A low speed ring PLL can generate
1190-
* signals of 1.25G and 3.125G for link speeds of 1G/2.5G. A high speed LC PLL can
1191-
* additionally generate a 10.3125G signal for 10G speeds. To drive the pair at different
1192-
* speeds each SerDes must use its own PLL. But what if the SerDess attached to the ring
1193-
* PLL suddenly needs 10G but the LC PLL is running at 1G? To avoid reconfiguring the
1194-
* "partner" SerDes we must choose wisely what assignment serves the current needs. The
1195-
* logic boils down to the following rules:
1188+
* A SerDes pair on RTL93xx is driven by a shared CMU with two PLLs:
1189+
*
1190+
* - a low speed ring PLL which can generate signals of 1.25G and 3.125G for link
1191+
* speeds of 1G/2.5G
1192+
* - a high speed LC PLL which can additionally generate a 10.3125G signal for
1193+
* 10G link speeds
1194+
*
1195+
* To drive the pair at different speeds, each SerDes must use its own PLL and we
1196+
* must wisely assign the PLLs to the SerDes based on their needs. The logic boils
1197+
* down to the following rules:
11961198
*
1197-
* - Use ring PLL for slow 1G speeds
1198-
* - Use LC PLL for fast 10G speeds
1199-
* - For 2.5G prefer ring over LC PLL
1199+
* - use ring PLL for slow 1G speeds
1200+
* - use LC PLL for fast 10G speeds
1201+
* - for 2.5G prefer ring over LC PLL
12001202
*
1201-
* However, when we want to configure 10G speed while the other SerDes is already using
1202-
* the LC PLL for a slower speed, there is no way to avoid reconfiguration. Note that
1203-
* this can even happen when the other SerDes is not actually in use, because changing
1204-
* the state of a SerDes back to RTL930X_SDS_OFF is not (yet) implemented.
1203+
* For the case that we want to configure 10G speed but the LC PLL is already used
1204+
* by the neighbor SerDes and running with a slower speed, there's no way to avoid
1205+
* reconfiguration. The neighbor SerDes is reconfigured online to the ring PLL.
12051206
*/
12061207

1207-
ret = nb_sds->ops->get_pll_select(nb_sds, &neighbor_pll);
1208+
if (hw_mode == RTPCS_SDS_MODE_OFF)
1209+
return 0;
1210+
1211+
ret = rtpcs_sds_select_pll_speed(hw_mode, &speed);
12081212
if (ret < 0)
12091213
return ret;
12101214

1211-
ret = rtpcs_93xx_sds_get_pll_config(nb_sds, neighbor_pll, &neighbor_speed);
1215+
if (nb_sds->hw_mode == RTPCS_SDS_MODE_OFF) {
1216+
pll = (speed == RTPCS_SDS_PLL_SPD_10000) ? RTPCS_SDS_PLL_TYPE_LC
1217+
: RTPCS_SDS_PLL_TYPE_RING;
1218+
goto pll_setup;
1219+
}
1220+
1221+
ret = nb_sds->ops->get_pll_select(nb_sds, &neighbor_pll);
12121222
if (ret < 0)
12131223
return ret;
12141224

1215-
ret = rtpcs_sds_select_pll_speed(hw_mode, &speed);
1225+
ret = rtpcs_93xx_sds_get_pll_config(nb_sds, neighbor_pll, &neighbor_speed);
12161226
if (ret < 0)
12171227
return ret;
12181228

1219-
if (nb_sds->hw_mode == RTPCS_SDS_MODE_OFF)
1220-
pll = speed == RTPCS_SDS_PLL_SPD_10000 ? RTPCS_SDS_PLL_TYPE_LC
1221-
: RTPCS_SDS_PLL_TYPE_RING;
1222-
else if (speed == neighbor_speed) {
1229+
if (speed == neighbor_speed) {
12231230
speed_changed = false;
12241231
pll = neighbor_pll;
12251232
} else if (neighbor_pll == RTPCS_SDS_PLL_TYPE_RING)
12261233
pll = RTPCS_SDS_PLL_TYPE_LC;
12271234
else if (speed == RTPCS_SDS_PLL_SPD_10000) {
12281235
pr_info("%s: SDS %d needs LC PLL, reconfigure SDS %d to use ring PLL\n",
12291236
__func__, sds->id, nb_sds->id);
1237+
12301238
ret = nb_sds->ops->reconfigure_to_pll(nb_sds, RTPCS_SDS_PLL_TYPE_RING);
12311239
if (ret < 0)
12321240
return ret;
@@ -1235,16 +1243,19 @@ static int rtpcs_93xx_sds_config_cmu(struct rtpcs_serdes *sds, enum rtpcs_sds_mo
12351243
} else
12361244
pll = RTPCS_SDS_PLL_TYPE_RING;
12371245

1238-
if (speed_changed)
1246+
pll_setup:
1247+
if (speed_changed) {
12391248
ret = rtpcs_93xx_sds_set_pll_config(sds, pll, speed);
1249+
if (ret < 0)
1250+
return ret;
1251+
}
12401252

12411253
ret = sds->ops->set_pll_select(sds, hw_mode, pll);
12421254
if (ret < 0)
12431255
return ret;
12441256

12451257
pr_info("%s: SDS %d using %s PLL for mode %d\n", __func__, sds->id,
12461258
pll == RTPCS_SDS_PLL_TYPE_LC ? "LC" : "ring", hw_mode);
1247-
12481259
return ret;
12491260
}
12501261

0 commit comments

Comments
 (0)