Index: sys/arm/allwinner/if_awg.c =================================================================== --- sys/arm/allwinner/if_awg.c +++ sys/arm/allwinner/if_awg.c @@ -123,6 +123,21 @@ #define EMAC_CLK_SRC_EXT_RGMII (1 << 0) #define EMAC_CLK_SRC_RGMII (2 << 0) +/* RTL PHY Registers */ +#define PHY_MAGIC 0x1c +#define PHY_MAGIC_NORXDELAY 0xb591 + +/* Extension Page Select */ +#define PHY_EPAGSR 0x1e +#define PHY_EPAGSR_MASK 0xff +#define PHY_EPAGSR_PAGE(n) ((n) & PHY_EPAGSR_MASK) +/* Page Select */ +#define PHY_PAGSEL 0x1f +#define PHY_PAGSEL_MASK 0x7 +#define PHY_PAGSEL_PAGE(n) ((n) & PHY_PAGSEL_MASK) +#define PHY_PAGSEL_EXT 0x7 + + /* Burst length of RX and TX DMA transfers */ static int awg_burst_len = BURST_LEN_DEFAULT; TUNABLE_INT("hw.awg.burst_len", &awg_burst_len); @@ -1252,6 +1267,18 @@ } } + if (sc->type == EMAC_A64 && strcmp(phy_type, "rgmii") == 0) { + /* + * The following sequence fixes gigabit functionality on the + * PIne64; configuring it for no RX delay causes it to stop + * frequently dropping packets, while still getting throughput. + */ + awg_miibus_writereg(dev, 1, PHY_PAGSEL, PHY_PAGSEL_EXT); + awg_miibus_writereg(dev, 1, PHY_EPAGSR, PHY_EPAGSR_PAGE(0xa4)); + awg_miibus_writereg(dev, 1, PHY_MAGIC, PHY_MAGIC_NORXDELAY); + awg_miibus_writereg(dev, 1, PHY_PAGSEL, PHY_PAGSEL_PAGE(0)); + } + error = 0; fail: