三 Linux 网络驱动-MAC、PHY层驱动框架( 五 )


第 62 行 , 获取“phy-”属性的值 , phy- 属性指定了 I. 网络外设所对 应获取 PHY 的设备节点 。在设备树的 fec1 和 fec2 两个节点中 phy- 属性值分别为:
phy-handle = <ðphy0>;phy-handle = <ðphy1>;
而和都定义在 mdio 子节点下 , 内容如下所示:
mdio {#address-cells = <1>;#size-cells = <0>;ethphy0: ethernet-phy@0 {compatible = "ethernet-phy-ieee802.3-c22";reg = <0>;};ethphy1: ethernet-phy@1 {compatible = "ethernet-phy-ieee802.3-c22";reg = <1>;};};
可以看出和都是与 MDIO 相关的 , 而 MDIO 接口是配置 PHY 芯片的 , 通 过一个 MDIO 接口可以配置多个 PHY 芯片 , 不同的 PHY 芯片通过不同的地址进行区别 。正点 原子 ALPHA 开发板中 ENET 的 PHY 地址为 0X00 , ENET2 的 PHY 地址为 0X01 。这两个 PHY 地址要通过设备树告诉 Linux 系统 , 下面两行代码@后面的数值就是 PHY 地址:
ethphy0: ethernet-phy@2ethphy1: ethernet-phy@1
并且和节点中的 reg 属性也是 PHY 地址 , 如果我们要更换其他的网络 PHY 芯片 , 第一步就是要修改设备树中的 PHY 地址 。
第 74 行 , 获取 PHY 工作模式 , 函数会读取属性 phy-mode 的值 , ” phy-mode”中保存了 PHY 的工作方式 , 即 PHY 是 RMII 还是 MII ,  中的 PHY 工作在 RMII 模式 , 设备树描述如下所示:
第 85、91、100、108 和 113 行 , 分别获取时钟 ipg、ahb、、 和 ptp , 对 应结构体有如下成员函数:
struct clk *clk_ipg;struct clk *clk_ahb;struct clk *clk_ref;struct clk *clk_enet_out;struct clk *clk_ptp;
第 120 行 , 使能时钟 。
第 136 行 , 调用函数复位 PHY 。
第 141 行 , 调用函数 ()初始化 enet , 此函数会分配队列、申请 dma、设置 MAC 地址 , 初始化的和成员 , 如图所示:
的和成变量分别初始化成了和。函数还会调用来设置 poll 函 数 , 说明 NXP 官方编写的此网络驱动是 NAPI 兼容驱动 , 
通过函数向网卡添加了一个 napi 示例 , 使用 NAPI 驱动要提供一个 poll 函数来轮询处理接收数据 , 此处的 poll 函数为  , 后面分析 网络数据接收处理流程的时候详细讲解此函数
最后 ,  函数会设置网络外设相关硬件寄存器.
第 146 行 , 从设备树中获取中断号 。
第 153 行 , 申请中断 , 中断处理函数为  , 重点!后面会分析此函数 。
第 161 行 , 从设备树中获取属性“fsl,”的值 , 也就是唤醒中断.
第 167 行 , 初始化完成量  , 用于一个执行单元等待另一个执行单元执行完某事.
第 168 行 , 函数完成 MII/RMII 接口的初始化.
下的 read 和 write 这两个成员变量分别是读/写 PHY 寄存器的操作函数 , 这里设置 为和  , 这两个函数就是 I.MX 系列 SOC 读写 PHY 内部 寄存器的函数 , 读取或者配置 PHY 寄存器都会通过这两个 MDIO 总线函数完成 。函数最终会向 Linux 内核注册 MIDO 总线.
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);5 } else {6err = mdiobus_register(fep->mii_bus);7 }
示例代码代码 第 1 行就是从设备树中获取 mdio 节点 , 如果节点存在的话就会通 过或者来向内核注册 MDIO 总线 , 如果采用设备树的话就 使用来注册 MDIO 总线 , 否则就使用函数 。