linux phy 初始化过程,以太网驱动的流程浅析(五)-mii_bus初始化以及phy id的获取

本文深入剖析Linux内核中以太网驱动的mii_bus初始化过程,包括struct mii_bus结构的初始化、注册以及PHY ID的获取。通过对关键函数的解读,如mdiobus_register、of_mdiobus_register等,阐述了如何从设备树中解析并创建PHY设备。文章强调了PHY ID获取的重要性,指出当PHY ID无法从寄存器中读取时,可能导致驱动加载失败的问题。同时,介绍了Realtek PHY在内核中的配置及驱动注册流程。
摘要由CSDN通过智能技术生成

以太网驱动的流程浅析(五)-mii_bus初始化以及phy id的获取

作者:heaven 发布于:2020-1-7 14:42

分类:Linux内核分析

我们继续沿着上一篇的以太网思路来继续分析,目的是为了学习以太网这块从应用层到底层的整块加载和匹配流程。

如下是本人调试过程中的一点经验分享,以太网驱动架构毕竟涉及的东西太多,如下仅仅是针对加载流程和围绕这个问题产生的分析过程和驱动加载流程部分,并不涉及以太网协议层的数据流程分析。

【硬件环境】         Imx6ul

【Linux kernel版本】   Linux4.1.15

【以太网phy】        Realtek8201f

1.1 mii_bus初始化以及phy id的获取

然后进行mii的一些初始化fec_enet_mii_init(pdev);

主要是对struct mii_bus这里的成员进行初始化

/*

* The Bus class for PHYs. Devices which provide access to

* PHYs should register using this structure

*/

struct mii_bus {

const char *name;

char id[MII_BUS_ID_SIZE];

void *priv;

int (*read)(struct mii_bus *bus, int phy_id, int regnum);

int (*write)(struct mii_bus *bus, int phy_id, int regnum, u16 val);

int (*reset)(struct mii_bus *bus);

/*

* A lock to ensure that only one thing can read/write

* the MDIO bus at a time

*/

struct mutex mdio_lock;

struct device *parent;

enum {

MDIOBUS_ALLOCATED = 1,

MDIOBUS_REGISTERED,

MDIOBUS_UNREGISTERED,

MDIOBUS_RELEASED,

} state;

struct device dev;

/* list of all PHYs on bus */

struct phy_device *phy_map[PHY_MAX_ADDR];

/* PHY addresses to be ignored when probing */

u32 phy_mask;

/*

* Pointer to an array of interrupts, each PHY's

* interrupt at the index matching its address

*/

int *irq;

};

#define to_mii_bus(d) container_of(d, struct mii_bus, dev)

fep->mii_bus = mdiobus_alloc();

if (fep->mii_bus == NULL) {

err = -ENOMEM;

goto err_out;

}

fep->mii_bus->name = "fec_enet_mii_bus";

fep->mii_bus->read = fec_enet_mdio_read;

fep->mii_bus->write = fec_enet_mdio_write;

snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",

pdev->name, fep->dev_id + 1);

fep->mii_bus->priv = fep;

fep->mii_bus->parent = &pdev->dev;

fep->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);

if (!fep->mii_bus->irq) {

err = -ENOMEM;

goto err_out_free_mdiobus;

}

for (i = 0; i < PHY_MAX_ADDR; i++)

fep->mii_bus->irq[i] = PHY_POLL;

并且会做注册mdiobus的工作

node = of_get_child_by_name(pdev->dev.of_node, "mdio");

if (node) {

err = of_mdiobus_register(fep->mii_bus, node);

of_node_put(node);

} else {

err = mdiobus_register(fep->mii_bus);

}

因为我们系统是使用device tree,因此会执行of_mdiobus_register

/**

* of_mdiobus_register - Register mii_bus and create PHYs from the device tree

* @mdio: pointer to mii_bus structure

* @np: pointer to device_node of MDIO bus.

*

* This function registers the mii_bus structure and registers a phy_device

* for each child node of @np.

*/

int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)

{

struct device_node *child;

const __be32 *paddr;

bool scanphys =

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值