• 基于335X的Linux网口驱动分析


    基于335X的linux网口驱动分析

    一、 系统构成

    1、  硬件平台 AM335X

    2、  LINUX内核版本 4.4.12

    二、 网口驱动构架(mdio部分)

    mdio网口驱动部分 使用 总线、设备、驱动模型,总结如下:

     

          

    若设备和驱动匹配,则执行

    davinci_mdio_probe

      --> mdiobus_register

       --> device_register

        --> mdiobus_scan

            --> get_phy_device

                --> get_phy_id // 读寄存器

                    -->  phy_device_create // 创建phy设备

                    --> INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); // !!!!!!初始化状态机函数

            --> phy_device_register

    经过以上步骤,由davinci_mdio_driver又创建出一个mdio_bus_type类型的bus.并扫描并创建了连接在bus上的phydev.

     

    若设备和驱动匹配,这时,也进行了phydev和phy_driver的匹配和绑定。则执行phy_probe

    以上总线下的设备和驱动的匹配过程如下,以platform_bus为例,其它总线也是这个流程

    platform_device跟platform_driver的匹配

    drivers/base/platform.c

    a. 注册 platform_driver 的过程:

    platform_driver_register

        __platform_driver_register

            drv->driver.probe = platform_drv_probe;

            driver_register

                bus_add_driver

                    klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);    // 把 platform_driver 放入 platform_bus_type 的driver链表中

                    driver_attach

                        bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);  // 对于plarform_bus_type下的每一个设备, 调用__driver_attach

                            __driver_attach

                                ret = driver_match_device(drv, dev);  // 判断dev和drv是否匹配成功

                                            return drv->bus->match ? drv->bus->match(dev, drv) : 1;  // 调用 platform_bus_type.match

                                driver_probe_device(drv, dev);

                                            really_probe

                                                drv->probe  // platform_drv_probe

                                                    platform_drv_probe

                                                        struct platform_driver *drv = to_platform_driver(_dev->driver);

                                                        drv->probe

                               

    b. 注册 platform_device 的过程:

    platform_device_register

        platform_device_add

            device_add

                bus_add_device

                    klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices); // 把 platform_device 放入 platform_bus_type的device链表中

                bus_probe_device(dev);

                    device_initial_probe

                        __device_attach

                            ret = bus_for_each_drv(dev->bus, NULL, &data, __device_attach_driver); // // 对于plarform_bus_type下的每一个driver, 调用 __device_attach_driver

                                        __device_attach_driver

                                            ret = driver_match_device(drv, dev);

                                                        return drv->bus->match ? drv->bus->match(dev, drv) : 1;  // 调用platform_bus_type.match

                                            driver_probe_device

                                               

    匹配函数是platform_bus_type.match, 即platform_match,

    匹配过程按优先顺序罗列如下:

    a. 比较 platform_dev.driver_override 和 platform_driver.drv->name

    b. 比较 platform_dev.dev.of_node的compatible属性 和 platform_driver.drv->of_match_table

    c. 比较 platform_dev.name 和 platform_driver.id_table

    d. 比较 platform_dev.name 和 platform_driver.drv->name

    有一个成功, 即匹配成功

    CPSW也是一个内部设备,也遵循总线、设备、驱动模型。CPSW设备从设备树中获得,DRV则是系统注册,匹配后进行probe,其主要执行过程如下:

    cpsw_probe

    --> CPSW平台数据、资源、DMA初始化、赋值netdev_ops、ethtool_ops

    --> 注册网络设备:register_netdev

    --> cpsw_ndo_open (此处根据实际经验得到,目前还没有从源代码级别解答出调用过程)

    --> cpsw_slave_open

        --> phy_connect (传递cpsw_adjust_link)

        --> bus_find_device_by_name (从mdio总线上查找device)

        --> to_phy_device (从device结构体中找到phy_device)

        --> phy_connect_direct (传递handler,初始化 ***)

            --> phy_attach_direct ()

                --> d->driver = &genphy_driver[GENPHY_DRV_1G].driver;(通用驱动赋值,3.17支持1G和10G)

                --> d->driver->probe (这里就调用到Generic PHY的检测函数phy_probe)

                --> device_bind_driver (绑定驱动到设备)

                --> phydev->attached_dev = dev; (有函数使用到attached_dev指针)

                --> phydev->state = PHY_READY; (将PHY状态标记为PHY_READY)

                --> phy_init_hw (硬件级的初始化,最后会调用genphy_config_init)

            --> phy_prepare_link (赋值cpsw_adjust_link为adjust_link)

            --> phy_start_machine (启动PHY状态机 ***)

            --> phy_start_interrupts (经测了,但好像没调用到这里)

    --> phy_start(PHY_READY变成PHY_UP)

    --> 其它的CPSW的初始化

  • 相关阅读:
    0xx_nodeJS
    0xx_jQuery
    0xx_正则表达式
    0xx_ES6
    centos重启关机命令
    tomcat服务开机启动脚本
    mysql授权总结
    centos创建文件命令
    svn如果无法连接有可能导致右键卡
    简单导出excel
  • 原文地址:https://www.cnblogs.com/lh03061238/p/10829761.html
Copyright © 2020-2023  润新知