Handle RTL8261BE SerDes configuration

The RTL8261BE uses a 10GBit QSGMII connection. Add handler for initial
configuration of the SerDes speed and upon link changes.
This commit is contained in:
logicog
2026-04-24 10:52:24 +02:00
parent c8e21b394b
commit 4f4f69ecc1
2 changed files with 64 additions and 31 deletions
+16 -11
View File
@@ -19,14 +19,6 @@ extern __xdata struct machine_runtime machine_detected;
*/ */
void static sds_init(void) void static sds_init(void)
{ {
/*
p001e.000d:9535 R02f8-00009535 R02f4-0000953a P000001.1e00000d:953a
p001e.000d:953a p001e.000d:953a R02f8-0000953a R02f4-00009530 P000001.1e00000d:9530
RTL8373:
p001e.000d:0010 R02f8-00000010 R02f4-0000001a P000001.1e00000d:b7fe
p001e.000d:0010 p001e.000d:0010 R02f8-00000010 R02f4-00000010 P000001.1e00000d:b7fe
*/
phy_read(0, PHY_MMD30, 0xd); phy_read(0, PHY_MMD30, 0xd);
uint16_t pval = SFR_DATA_U16; uint16_t pval = SFR_DATA_U16;
@@ -55,6 +47,8 @@ void static sds_init(void)
uint16_t pval; uint16_t pval;
print_string(" N-settings"); print_string(" N-settings");
if (machine.n_10g)
print_string(" - 10g");
// Serdes 0 RX PN swap for 64B/66B // Serdes 0 RX PN swap for 64B/66B
sds_read(1, 6, 2); sds_read(1, 6, 2);
pval = SFR_DATA_U16; pval = SFR_DATA_U16;
@@ -70,6 +64,7 @@ void static sds_init(void)
pval = SFR_DATA_U16; pval = SFR_DATA_U16;
sds_write_v(0, 6, 2, pval | 0x2000); sds_write_v(0, 6, 2, pval | 0x2000);
if (!machine.n_10g) {
if (machine_detected.isRTL8373) { if (machine_detected.isRTL8373) {
// RTL8224: Serdes 0 RX PN swap for 64B/66B // RTL8224: Serdes 0 RX PN swap for 64B/66B
// We assume that RTL8373N always paired with RTL8224N. // We assume that RTL8373N always paired with RTL8224N.
@@ -83,10 +78,17 @@ void static sds_init(void)
sds_write_v(0, 0, 0, pval | 0x200); sds_write_v(0, 0, 0, pval | 0x200);
} }
} }
if (machine.n_10g) {
reg_read_m(RTL837X_CFG_PHY_MDI_REVERSE);
sfr_mask_data(0, 0x0f,0x0c);
reg_write_m(RTL837X_CFG_PHY_MDI_REVERSE);
REG_SET(RTL837X_CFG_PHY_TX_POLARITY_SWAP, 0x0000596a);
}
}
} }
void rtl8373_init(void) __banked void rtl8373_init(void)
{ {
print_string("\nrtl8373_init called\n"); print_string("\nrtl8373_init called\n");
@@ -183,7 +185,7 @@ void rtl8373_init(void) __banked
} }
void rtl8372_init(void) __banked void rtl8372_init(void)
{ {
print_string("\nrtl8372_init called\n"); print_string("\nrtl8372_init called\n");
@@ -192,11 +194,14 @@ void rtl8372_init(void) __banked
phy_config(3); // PHY configuration: all internal PHYs? phy_config(3); // PHY configuration: all internal PHYs?
// Set the MAC SerDes Modes Bits 0-4: SDS 0 = 0x2 (0x2), Bits 5-9: SDS 1: 1f (off) // Set the MAC SerDes Modes Bits 0-4: SDS 0 = 0x2 (0x2), Bits 5-9: SDS 1: 1f (off)
// r7b20:00000bff R7b20-00000bff r7b20:00000bff R7b20-00000bff r7b20:00000bff R7b20-000003ff r7b20:000003ff R7b20-000003e2 r7b20:000003e2 R7b20-000003e2 // r7b20:00000bff R7b20-00000bff r7b20:00000bff R7b20-00000bff r7b20:00000bff R7b20-000003ff r7b20:000003ff R7b20-000003e2 r7b20:000003e2 R7b20-000003e2
if (machine.n_10g) {
REG_SET(RTL837X_REG_SDS_MODES, 0x3ed); // Disable SFP for now, set RTL8261BE SDS 0 to 0xd
} else {
reg_read_m(RTL837X_REG_SDS_MODES); reg_read_m(RTL837X_REG_SDS_MODES);
sfr_mask_data(1, 0, 0x03); sfr_mask_data(1, 0, 0x03);
sfr_mask_data(0, 0, 0xe2); sfr_mask_data(0, 0, 0xe2);
reg_write_m(RTL837X_REG_SDS_MODES); reg_write_m(RTL837X_REG_SDS_MODES);
}
// r0a90:000000f3 R0a90-000000fc // r0a90:000000f3 R0a90-000000fc
reg_read_m(RTL837X_CFG_PHY_MDI_REVERSE); reg_read_m(RTL837X_CFG_PHY_MDI_REVERSE);
sfr_mask_data(0, 0x0f, 0x0c); sfr_mask_data(0, 0x0f, 0x0c);
+33 -5
View File
@@ -867,13 +867,14 @@ void early_boot_handle_button(void)
* to connect to an SFP module or a PHY * to connect to an SFP module or a PHY
* Valid modes are SDS_10GR, SDS_QXGMII, SDS_HISGMII, SDS_HSG, SDS_SGMII and SDS_1000BX_FIBER * Valid modes are SDS_10GR, SDS_QXGMII, SDS_HISGMII, SDS_HSG, SDS_SGMII and SDS_1000BX_FIBER
* The SerDes ID may be 0 or 1 for RTL8272 and 0-2 for RTL8373 * The SerDes ID may be 0 or 1 for RTL8272 and 0-2 for RTL8373
* SDS_QXGMII is used for 10G Fiber, RTL8224 and RTL8261BE
*/ */
void sds_config(uint8_t sds, uint8_t mode) void sds_config(uint8_t sds, uint8_t mode)
{ {
print_string("sds_config sds: "); print_byte(sds); print_string(", mode: "); print_byte(mode); write_char('\n'); print_string("sds_config sds: "); print_byte(sds); print_string(", mode: "); print_byte(mode); write_char('\n');
sds_config_mac(sds, mode); sds_config_mac(sds, mode);
if (mode == SDS_10GR || mode == SDS_QXGMII) // 10G Fiber, 10G connection to RTL8224 if (mode == SDS_10GR || mode == SDS_QXGMII)
sds_write_v(sds, 0x21, 0x10, 0x4480); // Q002110:6480 sds_write_v(sds, 0x21, 0x10, 0x4480); // Q002110:6480
else else
sds_write_v(sds, 0x21, 0x10, 0x6480); // Q002110:6480 sds_write_v(sds, 0x21, 0x10, 0x6480); // Q002110:6480
@@ -909,7 +910,7 @@ void sds_config(uint8_t sds, uint8_t mode)
} }
sds_write_v(sds, 0x36, 0x10, v); // Q003610:0200 sds_write_v(sds, 0x36, 0x10, v); // Q003610:0200
if (page == 0x2e) { // 10G Fiber if (page == 0x2e) { // 10G Fiber / SDS_QXGMII
sds_write_v(sds, page, 0x04, 0x0080); // Q012e04:0080 sds_write_v(sds, page, 0x04, 0x0080); // Q012e04:0080
sds_write_v(sds, page, 0x06, 0x0408); // Q012e06:0408 sds_write_v(sds, page, 0x06, 0x0408); // Q012e06:0408
sds_write_v(sds, page, 0x07, 0x020d); // Q012e07:020d sds_write_v(sds, page, 0x07, 0x020d); // Q012e07:020d
@@ -938,6 +939,30 @@ void sds_config(uint8_t sds, uint8_t mode)
sds_write_v(sds, 0x07, 0x0c, 0x9401); // Q00070c:9401 sds_write_v(sds, 0x07, 0x0c, 0x9401); // Q00070c:9401
sds_write_v(sds, 0x1f, 0x0b, 0x0003); // Q001f0b:0003 sds_write_v(sds, 0x1f, 0x0b, 0x0003); // Q001f0b:0003
sds_write_v(sds, 0x06, 0x03, 0xc45c); // Q000603:c45c sds_write_v(sds, 0x06, 0x03, 0xc45c); // Q000603:c45c
// RTL8261BE
if (machine.n_10g && mode == SDS_QXGMII) {
sds_write_v(sds, 0x06, 0x1f, 0x2100); // Q00061f:2100
sds_write_v(sds, 0x07, 0x11, 0x054f); // Q000711:054f
sds_write_v(sds, 0x20, 0x00, 0x0030); // Q002000:0030
sds_write_v(sds, 0x20, 0x00, 0x0010); // Q002000:0010
sds_write_v(sds, 0x20, 0x00, 0x0050); // Q002000:0050
sds_write_v(sds, 0x20, 0x00, 0x00d0); // Q002000:00d0
sds_write_v(sds, 0x20, 0x00, 0x0cd0); // Q002000:0cd0
sds_write_v(sds, 0x20, 0x00, 0x04d0); // Q002000:04d0
sds_write_v(sds, 0x20, 0x00, 0x04d0); // Q002000:04d0
sds_write_v(sds, 0x20, 0x00, 0x0cd0); // Q002000:0cd0
sds_write_v(sds, 0x20, 0x00, 0x00d0); // Q002000:00d0
sds_write_v(sds, 0x20, 0x00, 0x00d0); // Q002000:00d0
sds_write_v(sds, 0x20, 0x00, 0x0050); // Q002000:0050
sds_write_v(sds, 0x20, 0x00, 0x0010); // Q002000:0010
sds_write_v(sds, 0x20, 0x00, 0x0010); // Q002000:0010
sds_write_v(sds, 0x20, 0x00, 0x0030); // Q002000:0030
sds_write_v(sds, 0x20, 0x00, 0x0000); // Q002000:0000
sds_write_v(sds, 0x1f, 0x00, 0x000b); // Q001f00:000b
sds_write_v(sds, 0x1f, 0x00, 0x0000); // Q001f00:0000
return;
}
if (mode != SDS_QXGMII) if (mode != SDS_QXGMII)
sds_write_v(sds, 0x06, 0x1f, 0x2100); // Q00061f:2100 sds_write_v(sds, 0x06, 0x1f, 0x2100); // Q00061f:2100
@@ -1342,13 +1367,17 @@ void idle(void)
uint8_t p5 = sfr_data[2] >> 4; uint8_t p5 = sfr_data[2] >> 4;
uint8_t p5_last = linkbits_last[2] >> 4; uint8_t p5_last = linkbits_last[2] >> 4;
cpy_4(linkbits_last, sfr_data); cpy_4(linkbits_last, sfr_data);
// Handle link change of the RTL8221 PHY, adjust SDS mode // Handle link change of the RTL8221 PHY, adjust SDS mode, RTL8261BE always uses SDS_QXGMII
if (p5_last != p5) { if (!machine.n_10g && p5_last != p5) {
if (p5 == 0x5) // 2.5GBit Mode if (p5 == 0x5) // 2.5GBit Mode
sds_config(0, SDS_HISGMII); sds_config(0, SDS_HISGMII);
else if (p5 == 0x2) // 1GBit else if (p5 == 0x2) // 1GBit
sds_config(0, SDS_SGMII); sds_config(0, SDS_SGMII);
} }
if (machine.n_10g)
sds_config(0, SDS_QXGMII);
if (machine.n_10g == 2)
sds_config(1, SDS_QXGMII);
} else { } else {
cpy_4(linkbits_last, sfr_data); cpy_4(linkbits_last, sfr_data);
} }
@@ -2016,7 +2045,6 @@ void main(void)
setup_i2c(); setup_i2c();
setup_sfp_gpio(); setup_sfp_gpio();
print_string(greeting); print_string(greeting);
print_string("\nClock register: "); print_string("\nClock register: ");