海思原厂提供的u-boot网卡驱动有问题,不能用,需要修改驱动程序。
网卡接口模式选择:
#define CONFIG_HIGMAC_PHY1_INTERFACE_MODE 2
模式为RGMII
网卡PHY地址:
#define CONFIG_HIGMAC_PHY1_ADDR 2
修改下面两个函数就可以了,主要是网卡的接口模式要是RGMII。
网卡型号:LAN8710A,需要通过网卡的SMI(Serial Management Interface)接口来配置网卡的PHY。
static int higmac_net_adjust_link(struct higmac_netdev_local *ld) { char *mii_name = higmac_board_info[ld->index].mii_name; int phy_addr = higmac_board_info[ld->index].phy_addr; enum if_mode phy_mode = higmac_board_info[ld->index].phy_intf; int stat = 0, speed = 0, is_duplex_half = 1, port_mode, phy_duplex; enum speed_mode speed_mode;
if (phy_addr == INVALID_PHY_ADDR) return stat;
phy_fixup(mii_name, phy_addr, phy_mode);
stat |= miiphy_link(mii_name, phy_addr) ? HIGMAC_LINKED : 0;
phy_duplex = miiphy_duplex(mii_name, phy_addr); if (phy_duplex == FULL) { stat |= HIGMAC_DUP_FULL; is_duplex_half = 0; }
speed = miiphy_speed(mii_name, phy_addr); switch (speed) { case _10BASET: stat |= HIGMAC_SPD_10M; speed_mode = speed_mode_10M; break; default: printf("wired, phy speed!\n"); case _100BASET: stat |= HIGMAC_SPD_100M; speed_mode = speed_mode_100M; break; case _1000BASET: stat |= HIGMAC_SPD_1000M; speed_mode = speed_mode_1000M; break; }
if (ld->link_stat != stat) { if (stat & HIGMAC_LINKED) { port_mode = calculate_port_mode(speed_mode, higmac_board_info[ld->index].phy_intf, is_duplex_half); //printf("port_mode:%#x\n",port_mode); //printf("ld->iobase:%#x\n",ld->iobase); port_mode |= 0x30; higmac_set_macif(ld, port_mode, speed_mode);
if (is_duplex_half) higmac_writel(ld, 0x0, MAC_DUPLEX_HALF_CTRL); else higmac_writel(ld, 0x1, MAC_DUPLEX_HALF_CTRL);
} ld->link_stat = stat; }
return stat; }
static int gmac_inited; static int mdio_register; static int higmac_init(void) { int ret = 0; struct higmac_netdev_local *ld; int i;
/* init once to save time */ if (!gmac_inited) { gmac_inited = 1; higmac_sys_init(); higmac_mdiobus_driver_init();
if (!mdio_register) { mdio_register = 1; miiphy_register(mdio_bus[0], higmac0_mdio_read, higmac0_mdio_write);
if (CONFIG_GMAC_NUMS == 2) { miiphy_register(mdio_bus[1], higmac1_mdio_read, higmac1_mdio_write); } } #if 0 /* disable PHY 1000M Mode */ miiphy_write(higmac_board_info[0].mii_name, higmac_board_info[0].phy_addr, PHY_1000BTCR, 0);
if (CONFIG_GMAC_NUMS == 2) miiphy_write(higmac_board_info[1].mii_name, higmac_board_info[1].phy_addr, PHY_1000BTCR, 0); #endif #if 1 unsigned short value; unsigned int oui; unsigned char model; unsigned char rev; unsigned char PHY_ADDR; int j; char *phy_name = higmac_board_info[0].mii_name;
for(j=2;j<32;j++) { if(miiphy_info (phy_name,j, &oui,&model, &rev) == 0) { //printf("PHY 0x%02X: ""OUI = 0x%04X, ""Model = 0x%02X, ""Rev = 0x%02X \n",j, oui,model, rev); if(oui == 0x1374) { // writel(0xc14fc1cf, 0x20050100); // writel(0xc14fdfcf, 0x20050100);
#if 1 PHY_ADDR = j; miiphy_write(phy_name,PHY_ADDR,PHY_BMCR,PHY_BMCR_RESET); udelay(1000); miiphy_read(phy_name,PHY_ADDR,PHY_BMCR,&value); value |= PHY_BMCR_AUTON; //value |=0x1140; miiphy_write(phy_name,PHY_ADDR,PHY_BMCR,value); udelay(1000);
miiphy_read(phy_name,PHY_ADDR,PHY_ANAR,&value); value |= (PHY_ANLPAR_TXFD|PHY_ANLPAR_TX|PHY_ANLPAR_10FD|PHY_ANLPAR_10); miiphy_write(phy_name,PHY_ADDR,PHY_ANAR,value); udelay(1000); //printf("PHY_ANAR:%lx\n",value); miiphy_write(phy_name,PHY_ADDR,0x1d,0x05); miiphy_write(phy_name,PHY_ADDR,0x1e,0x0100); //printf("CONFIG RGMII\n"); #endif } else if(oui == 0x01f0) { //writel(0x1, 0x120f0138); //writel(0x1, 0x120f013c); //writel(0x1, 0x120f0140); /* SDK BUG */ writel(0x3f, 0x1204008c);
#if 1 PHY_ADDR = j; //miiphy_write(phy_name,PHY_ADDR,PHY_BMCR,PHY_BMCR_RESET); miiphy_reset(higmac_board_info[0].mii_name, higmac_board_info[0].phy_addr); udelay(1000); miiphy_read(phy_name,PHY_ADDR,PHY_BMCR,&value); value |= PHY_BMCR_AUTON; miiphy_write(phy_name,PHY_ADDR,PHY_BMCR,value);
miiphy_read(phy_name,PHY_ADDR,PHY_ANAR,&value); value |= (PHY_ANLPAR_TXFD|PHY_ANLPAR_TX|PHY_ANLPAR_10FD|PHY_ANLPAR_10); miiphy_write(phy_name,PHY_ADDR,PHY_ANAR,value); udelay(1000);
//printf("rgmii0_col = 0x%lx\n",readl(0x200f0000+0x1b8)); miiphy_read(phy_name,PHY_ADDR,PHY_MIPGSR,&value); //printf("value = 0x%lx\n",value); //printf("CONFIG MII\n"); #endif } break; } }
if(j == 32) { printf("NOFOUND PHY\n"); } #endif
#if 0 miiphy_reset(higmac_board_info[0].mii_name, higmac_board_info[0].phy_addr);
if (CONFIG_GMAC_NUMS == 2) miiphy_reset(higmac_board_info[1].mii_name, higmac_board_info[1].phy_addr); #endif for_each_gmac_netdev_local_priv(ld, i) { higmac_glb_preinit_dummy(ld);
ret = higmac_set_hwq_depth(ld); if (ret) { printf("init eth%d hw desc depth fail!\n", i); goto glb_init; }
ret = higmac_init_hw_desc_queue(ld); if (ret) { printf("init eth%d hw desc queue fail!\n", i); goto hw_desc_init; } } }
ret = select_current_linked_phy(); if (ret) goto mdiobus_init;
higmac_desc_enable(current_ld, RX_OUTCFF_WR_DESC_ENA|RX_CFF_RD_DESC_ENA); higmac_writel_bits(current_ld, 1, PORT_EN, BITS_RX_EN);
higmac_writel_bits(current_ld, 1, PORT_EN, BITS_TX_EN); higmac_desc_enable(current_ld, TX_OUTCFF_WR_DESC_ENA|TX_CFF_RD_DESC_ENA);
return 0;
hw_desc_init: glb_init: higmac_mdiobus_driver_exit();
mdiobus_init: higmac_sys_exit();
return ret; } |