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

摘要:
然后执行phy_探针总线下设备和驱动程序的匹配过程如下_以总线为例。其他总线也是此过程的平台_设备和平台_驱动程序匹配驱动程序/base/platform.ca。注册平台_驱动进程:平台_驱动器_注册器_平台_驱动器注册器-˃驱动程序。探针=平台_ drv_探针;驱动程序寄存器总线添加驱动程序列表添加尾部;//将platform_驱动程序放入platform_ bus_驱动程序列表中的类型_ attachbus_ for _ each_ dev;//对于plarform_bus_对于类型下的每个设备,call__driver_attach_driver_attachet=driver_match_device;//判断dev和drv是否匹配成功返回drv-˃bus-˃match?

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

一、 系统构成

1、  硬件平台 AM335X

2、  LINUX内核版本 4.4.12

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

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

 基于335X的Linux网口驱动分析第1张

      

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

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.

 基于335X的Linux网口驱动分析第2张

若设备和驱动匹配,这时,也进行了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的初始化

免责声明:文章转载自《基于335X的Linux网口驱动分析》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇A garbage collector for C and C++matlab工具包下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

linux上systemctl使用

转载:https://www.cnblogs.com/zdz8207/p/linux-systemctl.html Linux服务器,服务管理--systemctl命令详解,设置开机自启动 syetemclt就是service和chkconfig这两个命令的整合,在CentOS 7就开始被使用了。 摘要: systemctl 是系统服务管理器命令,它实际上...

Android研究Android系统初始化程序init和初始化配置文件init.rc分析[zz]

上篇中讲到linux内核启动与android启动的衔接是linux内核根据约定,在启动的最后执行android的init进程。init进程主要工作是首先是解析init.rc等配置文件,之后充当property service。本文收集两篇文章,能够很好的理解init的逻辑和init.rc配置文件的语法和使用方法。 1. init程序逻辑 文章引用地址:一篇...

linux安装配置jdk、tomcat、开机自启动

1、安装JDK 1.1、官网下载jdk 1.2、源码包解压 jdk源码包上传到/usr/local(软件一般安装到这个目录) 使用解压命令解压 [root@localhost local]# tar -zxvf jdk-8u301-linux-x64.tar.gz 1.3、配置jdk环境变量 /etc/profile文件的改变会涉及到系统的环境,我们要将j...

Linux下Redis的安装和部署

一、Redis介绍 Redis是当前比较热门的NOSQL系统之一,它是一个key-value存储系统。和Memcache类似,但很大程度补偿了Memcache的不足,它支持存储的value类型相对更多,包括string、list、set、zset和hash。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作。在此基础上...

教你摸清 Linux PC 的性能底细?

导读 基准测试是一项测试或一系列测试,用来确定某个计算机硬件运行起来的状况有多好。在许多情况下,“基准测试”实际上等同于“压力测试”。通过测试硬件的极限,然后可以将测得的结果与其他硬件测得的结果作一番比较。 大多数基准测试旨在模拟 PC 在实际情形下遇到的那种工作负载。正因为如此,基准测试几乎就是获得定量数据、了解系统性能如何的唯一方法――如果你的数...

git从远程仓库gitLab上拉取指定分支到本地仓库

例如:将gitLab 上的dev分支拉取到本地 1》与远程仓库建立连接:git remote add origin XXXXX.git 2》使用git branch 查看本地是否具有dev分支 3》如果没有git fetch origin dev 4》git checkout -b dev origin/dev在本地创建分支dev并切换到该分支 5》gi...