以太网驱动的流程浅析(五)-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 =