hi3520dv300 u-boot 网卡驱动移植

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

你可能感兴趣的:(移动开发,android,framework,linux)