Linux设备驱动安装的基本过程

在windows系统里面,如果发现新的硬件设备但是系统没有可以用的自带驱动程序,那用户就得自己安装驱动。Linux内核的设计也是一样,下面就以marvel PHY设备的发现和驱动安装(即模块插入)为例说明一般嵌入式里设备的发现和安装过程。
假如某个小系统里面,soc上集成了MAC,然后外面通过MDIO BUS接了一个PHY芯片,那么在定制内核的时候肯定会选择libphy以及相应的SOC MDIO BUS驱动,内核启动的时候,MDIO BUS驱动会调用mdiobus_register()来向内核注册bus,注册的过程中会循环调用mdiobus_scan去发现PHY设备,get_phy_device()做的就是就是读取PHY芯片的ID,如果发现MDIO BUS挂了PHY设备,那就为这个PHY设备创建phy_device实例,并且为其分配addr。这样内核里就有为PHY设备初始化了数据结构了,也就是说发现并创建了设备(所有的设备都会有struct device结构)。
struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
{
struct phy_device *phydev;
int err;

phydev = get_phy_device(bus, addr, false);
if (IS_ERR(phydev) || phydev == NULL)
return phydev;

err = phy_device_register(phydev);
if (err) {
phy_device_free(phydev);
return NULL;
}

return phydev;
}

那么接下来就是安装驱动的过程。
我们假设驱动模块是内核起来后加载的,那么来看看驱动的实现。
static struct phy_driver marvell_drivers[] = {
{
.phy_id = MARVELL_PHY_ID_88E1101,
.phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "Marvell 88E1101",
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_aneg = &marvell_config_aneg,
.read_status = &genphy_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
.driver = { .owner = THIS_MODULE },
},

PHY的驱动模块定义了driver数据结构,一系列API。而驱动模块插入时,调用phy_drivers_register向系统注册此driver,并将其和mdio bus type关联。那如何将这个驱动代码和刚才发现的PHY设备关联起来呢?这里的phy_id和phy_id_mask是关键。 phy_drivers_register最终会调用driver_attach在这个driver关联的bus上面为每个设备match这个driver。主要代码在下面两个函数:
static inline int driver_match_device(struct device_driver *drv,
        struct device *dev)
{
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}

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);

if (of_driver_match_device(dev, drv))
return 1;

if (phydrv->match_phy_device)
return phydrv->match_phy_device(phydev);

return ((phydrv->phy_id & phydrv->phy_id_mask) ==
(phydev->phy_id & phydrv->phy_id_mask));
}
前面发现设备的时候设备已经记录了自己的phy_id,这个时候driver又是和这个phy_id匹配,所以驱动就匹配上了PHY设备。这之后phy_device->drv就会指向marvell_drivers。
整个过程的设计十分科学合理。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值