Amlogic A113x2 AN8801 无法协商到 1000M 的修复

问题现象

PHY 已识别后,含 1000baseT 的自协商失败(carrier=0);

ethtool -s eth0 autoneg off speed 100 duplex full 可通。

问题根因

phy-mode=rgmii 未让 PHY 加 RX delay,RGMII RX 采样窗口不对;

强制 MDI-X 也常导致部分交换机/网线 aneg 失败。

解决方案

  1. DTS phy-mode = "rgmii-rxid"

  2. max-speed = <1000>(不要用旧的 max-speed=<100> 绕过)

  3. 驱动侧(已在 an8801-phy-driver.patch 的 an8801.c):

  • rgmii-rxid 时写 RX delay: 0x1021C02C = 0x01000003 (BIT(24)|STEP_3, 无 ALIGN)

  • AUTO-MDIX

代码实现

修改a5_a113x2_av400_1g_spk.dts

复制代码
--- a/common_drivers/arch/arm64/boot/dts/amlogic/a5_a113x2_av400_1g_spk.dts
+++ b/common_drivers/arch/arm64/boot/dts/amlogic/a5_a113x2_av400_1g_spk.dts
@@ -1331,19 +1331,22 @@
 &external_phy {
 	/*
 	 * Sole owner of GPIOZ_15: AN8801 probe pulses RESET_N.
 	 * Must NOT also appear in &ethmac pinctrl (pin claim conflict).
+	 * max-speed=1000: rgmii-rxid + PHY RX delay (0x1021C02C=0x01000003)
+	 * makes 1000baseT autoneg work (do not cap at 100).
 	 */
 	an8801-reset-gpios = <&gpio GPIOZ_15 GPIO_ACTIVE_LOW>;
+	max-speed = <1000>;
 };
 
 &ethmac {
 	pinctrl-0 = <&eth_pins>, <&eth_rgmii_pins>;
 	pinctrl-names = "default";
 	status = "okay";
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-rxid";
 	phy-handle = <&external_phy>;
 	amlogic,tx-delay-ns = <2>;
 	/* No snps,reset-gpio / no eth_phy_reset_pins: avoid claiming Z15 */
 };

修改meson-a5.dtsi

复制代码
--- a/common_drivers/arch/arm64/boot/dts/amlogic/meson-a5.dtsi
+++ b/common_drivers/arch/arm64/boot/dts/amlogic/meson-a5.dtsi
@@ -1046,14 +1046,16 @@
 				#address-cells = <1>;
 				#size-cells = <0>;
 				compatible = "snps,dwmac-mdio";
 				/*
 				 * Airoha AN8801R RESET_N = GPIOZ_15, owned by PHY driver.
 				 * Board DTS: an8801-reset-gpios only (probe-time pulse).
 				 * No snps,reset-gpio / reset-gpios (avoid boot re-assert).
+				 * Board phy-mode must be "rgmii-rxid" so PHY applies
+				 * RX delay 0x1021C02C=0x01000003 and 1000M aneg can pass.
 				 */
 				external_phy: ethernet-phy@1 {
 					compatible = "ethernet-phy-idc0ff.0421";
 					reg = <1>;
 					max-speed = <1000>;
 				};
 			};

修改驱动common/drivers/net/phy/an8801.c

复制代码
static int an8801r_rgmii_rxdelay(struct phy_device *phydev, u16 delay, u8 align)
 {
-	u32 reg_val = delay & RGMII_DELAY_STEP_MASK;
+	u32 reg_val;
 
-	/* align */
-	if (align) {
-		reg_val |= RGMII_RXDELAY_ALIGN;
-		dev_info(phydev_dev(phydev), "Rxdelay align\n");
-	}
-	reg_val |= RGMII_RXDELAY_FORCE_MODE;
+	/*
+	 * Equivalent to userspace MDIO sequence (page 4 PBUS write):
+	 *   wr 0x1f,4; 0x10=0; 0x11=0x1021; 0x12=0xc02c;
+	 *   0x13=0x0100; 0x14=0x0003; restore 0x1f
+	 * â†' 0x1021C02C = 0x01000003 (BIT(24)|step), no RGMII_RXDELAY_ALIGN
+	 */
+	(void)align;
+	reg_val = BIT(24) | (delay & RGMII_DELAY_STEP_MASK);
 	air_buckpbus_reg_write(phydev, 0x1021C02C, reg_val);
 	reg_val = 0;
 	air_buckpbus_reg_read(phydev, 0x1021C02C, &reg_val);
 	dev_info(phydev_dev(phydev),
-		"Force rxdelay = %d(0x%x)\n", delay, reg_val);
+		"Force rxdelay step=%d reg=0x%x (expect force|step)\n",
+		delay, reg_val);
 	return 0;
 }
 
@@ -588,11 +591,12 @@
 		an8801r_rgmii_txdelay(phydev, AIR_RGMII_DELAY_STEP_4);
 		break;
 	case PHY_INTERFACE_MODE_RGMII_RXID:
-		an8801r_rgmii_rxdelay(phydev, AIR_RGMII_DELAY_NOSTEP, TRUE);
+		/* Board validated: 0x1021C02C = 0x01000003 */
+		an8801r_rgmii_rxdelay(phydev, AIR_RGMII_DELAY_STEP_3, FALSE);
 		break;
 	case PHY_INTERFACE_MODE_RGMII_ID:
 		an8801r_rgmii_txdelay(phydev, AIR_RGMII_DELAY_STEP_4);
-		an8801r_rgmii_rxdelay(phydev, AIR_RGMII_DELAY_NOSTEP, TRUE);
+		an8801r_rgmii_rxdelay(phydev, AIR_RGMII_DELAY_STEP_3, FALSE);
 		break;
 	case PHY_INTERFACE_MODE_RGMII:
 	default: