phy: advertise half duplex only when half duplex was asked for

The 100M branch of phy_set_speed() was missing an else. A port set to 100M
half wrote 0x1481, walked into the next if, found duplex was not 1, took its
else and overwrote the register with 0x1581 straight away, so it advertised
100BASE-TX half and full both. That is what asking for both is meant to do,
and forcing half is something people do to match a partner that cannot
negotiate, so the link comes up looking fine and misbehaves under load.

Bit 7 is 100BASE-TX half and bit 8 is full, which makes 0x1481, 0x1501 and
0x1581 half, full and both, the same shape as 0x1421, 0x1441 and 0x1461 in
the 10M branch above.

Both branches now choose the advertisement into a variable and write it once,
and they compare against the PHY_DUPLEX_* names instead of 0, 1 and whatever
is left. Same values reach the PHY; BANK2 loses 92 bytes.
This commit is contained in:
d00f committed 2026-09-08 23:49:11 +02:00
1 parent 412098d0ed
commit fe3da0c7a5
1 file changed
+14 -10
+14 -10
View File
@@ -332,21 +332,25 @@ void phy_set_speed(void) __banked
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13)
if (phy_settings.speed == PHY_SPEED_10M) {
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001);
if (!phy_settings.duplex)
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1421);
else if (phy_settings.duplex == 1)
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1441);
uint16_t adv10;
if (phy_settings.duplex == PHY_DUPLEX_HALF)
adv10 = 0x1421;
else if (phy_settings.duplex == PHY_DUPLEX_FULL)
adv10 = 0x1441;
else
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1461);
adv10 = 0x1461;
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, adv10);
phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000);
} else if (phy_settings.speed == PHY_SPEED_100M) {
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001);
if (!phy_settings.duplex)
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1481);
else if (phy_settings.duplex == 1)
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1501);
uint16_t adv100;
if (phy_settings.duplex == PHY_DUPLEX_HALF)
adv100 = 0x1481;
else if (phy_settings.duplex == PHY_DUPLEX_FULL)
adv100 = 0x1501;
else
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1581);
adv100 = 0x1581;
phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, adv100);
phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000);
} else {
// AN Advertisement Register (MMD 7.0x0010)