文章目录
写在前面
本小节主要分析一下rk平台px30 GAMC网卡驱动如何检测的网线拔插。linux内核版本 :4.4
拔插网线的调用堆栈
初始化队列
get_phy_device
phy_device_create(bus, addr, phy_id, is_c45, &c45_ids);
INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine);
phy_state_machine //循环检测网卡状态 - 状态机
rkl8367_read_status
genphy_update_link
mdiobus_read
bus->read
//bus->read 也就是这个
static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
{
unsigned int data = 0;
int ret = 0;
ret = rtl8367c_getAsicPHYReg((unsigned int)phyaddr, (unsigned int)phyreg, &data);
<span class="token keyword">if</span><span class="token punctuation">(</span>ret <span class="token operator">!=</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"ERROR: %s phyaddr: %x phyreg: %x return %x \n"</span><span class="token punctuation">,</span> <span class="token constant">__func__</span><span class="token punctuation">,</span> phyaddr<span class="token punctuation">,</span> phyreg<span class="token punctuation">,</span> ret<span class="token punctuation">)</span><span class="token punctuation">;</span>
ret <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
<span class="token comment">//printk("%s - phyaddr: %x, phyreg: %x, data: %x \n", __func__, phyaddr, phyreg, data);</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span>data<span class="token punctuation">;</span>
}
//重点看一下这个匹配函数函数,使用这个函数,匹配phy device的id和phy driver的id
/** * mdio_bus_match - determine if given PHY driver supports the given PHY device * @dev: target PHY device * @drv: given PHY driver * * Description: Given a PHY device, and a PHY driver, return 1 if * the driver supports the device. Otherwise, return 0. */ static int mdio_bus_match(struct device *dev, struct device_driver *drv) { struct phy_device *phydev = to_phy_device(dev); struct phy_driver *phydrv = to_phy_driver(drv); const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids); int i;<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">of_driver_match_device</span><span class="token punctuation">(</span>dev<span class="token punctuation">,</span> drv<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token number">1</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>phydrv<span class="token operator">-></span>match_phy_device<span class="token punctuation">)</span> <span class="token keyword">return</span> phydrv<span class="token operator">-></span><span class="token function">match_phy_device</span><span class="token punctuation">(</span>phydev<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>phydev<span class="token operator">-></span>is_c45<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator"><</span> num_ids<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token punctuation">(</span>phydev<span class="token operator">-></span>c45_ids<span class="token punctuation">.</span>devices_in_package <span class="token operator">&</span> <span class="token punctuation">(</span><span class="token number">1</span> <span class="token operator"><<</span> i<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">continue</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>phydrv<span class="token operator">-></span>phy_id <span class="token operator">&</span> phydrv<span class="token operator">-></span>phy_id_mask<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token punctuation">(</span>phydev<span class="token operator">-></span>c45_ids<span class="token punctuation">.</span>device_ids<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">&</span> phydrv<span class="token operator">-></span>phy_id_mask<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token number">1</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">// 在这里给设备匹配驱动 </span> <span class="token keyword">return</span> <span class="token punctuation">(</span>phydrv<span class="token operator">-></span>phy_id <span class="token operator">&</span> phydrv<span class="token operator">-></span>phy_id_mask<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token punctuation">(</span>phydev<span class="token operator">-></span>phy_id <span class="token operator">&</span> phydrv<span class="token operator">-></span>phy_id_mask<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
也就是phy driver里的这个结构体
static struct phy_driver genphy_driver[] =
{
.phy_id = 0x001cc942,//这里一定要跟真实探测到的设备id对应,如果发现没有掉用到正确的bus->read ,需要检查一下这个id
.phy_id_mask = 0x001fffff,// 关键位
.name = "rtl8367 PHY",
.soft_reset = rkl8367_soft_reset,
.config_init = rkl8367_config_init,
.features = PHY_GBIT_FEATURES | SUPPORTED_MII |
SUPPORTED_AUI | SUPPORTED_FIBRE |
SUPPORTED_BNC,
.config_aneg = rkl8367_config_aneg,
.read_status = rkl8367_read_status,
.suspend = rkl8367_suspend,
.resume = rkl8367_resume,
.driver = {.owner = THIS_MODULE, },
} ;
本文详细解析了rk平台px30GAMC网卡驱动中,当拔插网线时的调用堆栈过程,重点讨论了初始化队列、状态机检测和MDIO_bus_match函数,以及PHY_device_create和phy_driver匹配的实现。通过阅读rtl8367c_getAsicPHYReg函数,了解了驱动如何获取PHY设备状态信息。

4274

被折叠的 条评论
为什么被折叠?



