前段时间在调试FT-M6678和C6678的板卡,结果中途来了一个T2080网络配置的更改需求,就临时处理了一下,花了一点功夫,记录下来,为大家做个参考。
这个问题完成后,就得继续开发FT-M6678了~
- uboot下面phy配置更改(board/freescale/tx208xrdb/eth_t208xrdb.c)
a. 配置芯片模式配置为BX1000_RGMII_50
miiphy_write(DEFAULT_FM_MDIO_NAME, 0x6, 0x1F, 0x106); //mode_cfg: 0010 = BX1000_RGMII_50
printf("phy write 0x1F by 0x106!\r\n");
miiphy_write(DEFAULT_FM_MDIO_NAME, 0x6, 0x0, 0x2100);
printf("phy write 0x0 by 0x2100!\r\n");
miiphy_write(DEFAULT_FM_MDIO_NAME, 0x6, 0x0, 0x140);
printf("phy write 0x0 by 0x140!\r\n");
miiphy_write(DEFAULT_FM_MDIO_NAME, 0x6, 0x1F, 0x102); //mode_cfg: 0010 = BX1000_RGMII_50
printf("phy write 0x1F by 0x102!\r\n");
miiphy_write(DEFAULT_FM_MDIO_NAME, 0x6, 0xD, 0x3);
miiphy_write(DEFAULT_FM_MDIO_NAME, 0x6, 0xE, 0x805D);
miiphy_write(DEFAULT_FM_MDIO_NAME, 0x6, 0xD, 0x4003);
miiphy_write(DEFAULT_FM_MDIO_NAME, 0x6, 0xE, 0x100);
miiphy_write(DEFAULT_FM_MDIO_NAME, 0x6, 0x1D, 0x0);
miiphy_write(DEFAULT_FM_MDIO_NAME, 0x6, 0x1E, 0x8000);
miiphy_write(DEFAULT_FM_MDIO_NAME, 0x6, 0x1D, 0x5);
miiphy_write(DEFAULT_FM_MDIO_NAME, 0x6, 0x1E, 0x100);
//dummy read status
miiphy_read(DEFAULT_FM_MDIO_NAME, 0x6, 0x1, &value);
-
更改phy.c(drivers/net/phy)
/**
- genphy_update_link - update link status in @phydev
- @phydev: target phy_device struct
- Description: Update the value in phydev->link to reflect the
- current link value. In order to do this, we need to read
- the status register twice, keeping the second value.
*/
int genphy_update_link(struct phy_device *phydev)
{
unsigned int mii_reg;
/* * Wait if the link is up, and autonegotiation is in progress * (ie - we're capable and it's not done) */ mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); /* * If we already saw the link up, and it hasn't gone down, then * we don't need to wait for autoneg again */ //modify if (phydev->addr != 6) { if (phydev->link && mii_reg & BMSR_LSTATUS) return 0; } else { if (mii_reg & BMSR_LSTATUS) { phydev->link = 1; printf("%s Force Mode", phydev->dev->name); phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, 0x140); return 0; } } if ((mii_reg & BMSR_ANEGCAPABLE) && !(mii_reg & BMSR_ANEGCOMPLETE)) { int i = 0; printf("%s Waiting for PHY auto negotiation to complete", phydev->dev->name); while (!(mii_reg & BMSR_ANEGCOMPLETE)) { /* * Timeout reached ? */ if (i > PHY_ANEG_TIMEOUT) { printf(" TIMEOUT !\n"); phydev->link = 0; return 0; } if (ctrlc()) { puts("user interrupt!\n"); phydev->link = 0; return -EINTR; } if ((i++ % 500) == 0) printf("."); udelay(1000); /* 1 ms */ mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); } printf(" done\n"); phydev->link = 1; } else { /* Read the link a second time to clear the latched state */ mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); if (mii_reg & BMSR_LSTATUS) phydev->link = 1; else phydev->link = 0; } return 0;
}
/*
-
Generic function which updates the speed and duplex. If
-
autonegotiation is enabled, it uses the AND of the link
-
partner's advertised capabilities and our advertised
-
capabilities. If autonegotiation is disabled, we use the
-
appropriate bits in the control register.
-
Stolen from Linux's mii.c and phy_device.c
*/
int genphy_parse_link(struct phy_device *phydev)
{
int mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);if (phydev->addr != 6)
{
/* We're using autonegotiation */
if (phydev->supported & SUPPORTED_Autoneg) {
u32 lpa = 0;
int gblpa = 0;
u32 estatus = 0;/* Check for gigabit capability */ if (phydev->supported & (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half)) { /* We want a list of states supported by * both PHYs in the link */ gblpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_STAT1000); if (gblpa < 0) { debug("Could not read MII_STAT1000. Ignoring gigabit capability\n"); gblpa = 0; } gblpa &= phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000) << 2; } /* Set the baseline so we only have to set them * if they're different */ phydev->speed = SPEED_10; phydev->duplex = DUPLEX_HALF; /* Check the gigabit fields */ if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) { phydev->speed = SPEED_1000; if (gblpa & PHY_1000BTSR_1000FD) phydev->duplex = DUPLEX_FULL; /* We're done! */ return 0; } lpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE); lpa &= phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA); if (lpa & (LPA_100FULL | LPA_100HALF)) { phydev->speed = SPEED_100; if (lpa & LPA_100FULL) phydev->duplex = DUPLEX_FULL; } else if (lpa & LPA_10FULL) phydev->duplex = DUPLEX_FULL; /* * Extended status may indicate that the PHY supports * 1000BASE-T/X even though the 1000BASE-T registers * are missing. In this case we can't tell whether the * peer also supports it, so we only check extended * status if the 1000BASE-T registers are actually * missing. */ if ((mii_reg & BMSR_ESTATEN) && !(mii_reg & BMSR_ERCAP)) estatus = phy_read(phydev, MDIO_DEVAD_NONE, MII_ESTATUS); if (estatus & (ESTATUS_1000_XFULL | ESTATUS_1000_XHALF | ESTATUS_1000_TFULL | ESTATUS_1000_THALF)) { phydev->speed = SPEED_1000; if (estatus & (ESTATUS_1000_XFULL | ESTATUS_1000_TFULL)) phydev->duplex = DUPLEX_FULL; } } else { u32 bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); phydev->speed = SPEED_10; phydev->duplex = DUPLEX_HALF; if (bmcr & BMCR_FULLDPLX) phydev->duplex = DUPLEX_FULL; if (bmcr & BMCR_SPEED1000) phydev->speed = SPEED_1000; else if (bmcr & BMCR_SPEED100) phydev->speed = SPEED_100; }
}
else
{
u32 bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);phydev->speed = SPEED_10; phydev->duplex = DUPLEX_HALF; if (bmcr & BMCR_FULLDPLX) phydev->duplex = DUPLEX_FULL; if (bmcr & BMCR_SPEED1000) phydev->speed = SPEED_1000; else if (bmcr & BMCR_SPEED100) phydev->speed = SPEED_100;
}
return 0;
}
-
在内核系统启动后,依次输入如下指令:
ifconfig fm1-mac1 192.168.1.130 up
ifconfig fm1-mac3 192.168.2.130 up
ethtool -s fm1-mac3 speed 1000 duplex full autoneg off
使用ethtool配置强制千兆全双工,自协商关闭,即可