海思原厂提供的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;
}