LAN8720 100M 掉线问题解决

最近在做一块板子的时候,使用的phy芯片为LAN8720,在使用的发现老是ping一段时间后自动掉线,从软件问题一直查找,最后发现是LAN8720掉线了,且wang网口绿灯一直常亮,拔线网线也是一样,黄灯不闪烁,且phy发热严重。问题出在本来网口电源是下面这样,但是在焊接时没有找到磁珠,就用0欧电阻代替,结果电源干扰大不稳定,换上磁珠后ping未出现网口掉线现象,发热现象明显减少。

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
LAN8720是一款常用的以太网PHY芯片,它可以通过RMII或MII接口与Linux系统连接。下面是一个可能的LAN8720 Linux驱动程序的示例代码: ``` #include <linux/module.h> #include <linux/kernel.h> #include <linux/i2c.h> #include <linux/netdevice.h> #include <linux/ethtool.h> #include <linux/of.h> #include <linux/of_device.h> /* LAN8720 PHY registers */ #define LAN8720_REG_BCR 0x00 /* Basic Control Register */ #define LAN8720_REG_BSR 0x01 /* Basic Status Register */ #define LAN8720_REG_PHYID1 0x02 /* PHY Identifier 1 */ #define LAN8720_REG_PHYID2 0x03 /* PHY Identifier 2 */ #define LAN8720_REG_ANAR 0x04 /* Auto-Negotiation Advertisement Register */ #define LAN8720_REG_ANLPAR 0x05 /* Auto-Negotiation Link Partner Ability Register */ #define LAN8720_REG_ANER 0x06 /* Auto-Negotiation Expansion Register */ #define LAN8720_REG_DSCR 0x10 /* PCS/TX Descriptor Register */ #define LAN8720_REG_DSCSR 0x11 /* PCS/TX Descriptor and Status Register */ #define LAN8720_REG_PHYCR 0x19 /* PHY Control Register */ #define LAN8720_PHY_RESET_DELAY_MS 100 struct lan8720_priv { struct device *dev; struct net_device *netdev; void __iomem *regs; }; static int lan8720_mdio_read(struct mii_bus *bus, int phy_addr, int reg_addr) { struct lan8720_priv *priv = bus->priv; void __iomem *regs = priv->regs; int val; writel(0x80000000 | (phy_addr << 23) | (reg_addr << 18), regs + LAN8720_REG_DSCR); while (!(readl(regs + LAN8720_REG_DSCSR) & 0x80000000)); val = readl(regs + LAN8720_REG_DSCR) & 0xffff; return val; } static int lan8720_mdio_write(struct mii_bus *bus, int phy_addr, int reg_addr, u16 val) { struct lan8720_priv *priv = bus->priv; void __iomem *regs = priv->regs; writel(0xc0000000 | (phy_addr << 23) | (reg_addr << 18) | val, regs + LAN8720_REG_DSCR); while (!(readl(regs + LAN8720_REG_DSCSR) & 0x80000000)); return 0; } static int lan8720_phy_reset(struct lan8720_priv *priv) { u16 val; /* Reset PHY */ lan8720_mdio_write(priv->netdev->mdio_bus, priv->netdev->phydev->addr, LAN8720_REG_BCR, 0x8000); msleep(LAN8720_PHY_RESET_DELAY_MS); /* Wait for PHY to come out of reset */ val = lan8720_mdio_read(priv->netdev->mdio_bus, priv->netdev->phydev->addr, LAN8720_REG_BCR); if (val & 0x8000) return -EBUSY; return 0; } static int lan8720_phy_init(struct lan8720_priv *priv) { u16 val; /* Reset PHY */ if (lan8720_phy_reset(priv)) return -EBUSY; /* Enable auto-negotiation */ lan8720_mdio_write(priv->netdev->mdio_bus, priv->netdev->phydev->addr, LAN8720_REG_BCR, 0x1000); /* Wait for auto-negotiation to complete */ do { val = lan8720_mdio_read(priv->netdev->mdio_bus, priv->netdev->phydev->addr, LAN8720_REG_BSR); } while (!(val & 0x0020)); /* Enable RX/TX */ lan8720_mdio_write(priv->netdev->mdio_bus, priv->netdev->phydev->addr, LAN8720_REG_BCR, 0x2000); return 0; } static int lan8720_probe(struct platform_device *pdev) { struct lan8720_priv *priv; struct net_device *netdev; struct device_node *np = pdev->dev.of_node; struct resource *res; int ret; /* Allocate private data */ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; /* Allocate netdev */ netdev = alloc_etherdev(sizeof(*priv)); if (!netdev) return -ENOMEM; /* Set netdev MAC address */ of_property_read_u8_array(np, "local-mac-address", netdev->dev_addr, ETH_ALEN); /* Initialize netdev */ netdev->netdev_ops = &lan8720_netdev_ops; netdev->ethtool_ops = &lan8720_ethtool_ops; netdev->needs_free_netdev = true; netif_napi_add(netdev, &priv->napi, lan8720_rx_napi, NAPI_POLL_WEIGHT); /* Allocate MDIO bus */ netdev->phydev = mdiobus_alloc(); if (!netdev->phydev) { free_netdev(netdev); return -ENOMEM; } /* Set MDIO bus parameters */ netdev->phydev->bus = priv->netdev->mdio_bus; netdev->phydev->mdio_read = lan8720_mdio_read; netdev->phydev->mdio_write = lan8720_mdio_write; netdev->phydev->priv = priv; /* Initialize PHY */ ret = lan8720_phy_init(priv); if (ret) { mdiobus_free(netdev->phydev->bus); free_netdev(netdev); return ret; } /* Set netdev device and add it to network interface */ priv->dev = &pdev->dev; priv->netdev = netdev; platform_set_drvdata(pdev, priv); ret = register_netdev(netdev); if (ret) { mdiobus_free(netdev->phydev->bus); free_netdev(netdev); return ret; } return 0; } static int lan8720_remove(struct platform_device *pdev) { struct lan8720_priv *priv = platform_get_drvdata(pdev); unregister_netdev(priv->netdev); mdiobus_free(priv->netdev->phydev->bus); free_netdev(priv->netdev); return 0; } static const struct of_device_id lan8720_of_match[] = { { .compatible = "smsc,lan8720" }, { }, }; MODULE_DEVICE_TABLE(of, lan8720_of_match); static struct platform_driver lan8720_driver = { .probe = lan8720_probe, .remove = lan8720_remove, .driver = { .name = "lan8720", .of_match_table = lan8720_of_match, }, }; module_platform_driver(lan8720_driver); MODULE_AUTHOR("Your Name Here"); MODULE_DESCRIPTION("LAN8720 driver"); MODULE_LICENSE("GPL"); ``` 需要注意的是,以上示例代码只是一个框架,实际的驱动程序需要根据硬件的具体特性进行实现。另外,该驱动程序还包含了一个NAPI驱动程序,以便在高速网络环境下进行数据接收。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值