phy子系统分析
来源:互联网 发布:无人机电调算法 编辑:程序博客网 时间:2024/05/22 06:29
linux PHY 驱动
firefly-3399
linux内核版本:4.4
MAC(Media Access Control)
1.网络硬件部分
2.驱动部分
参考博客
http://www.jianshu.com/p/77bb0ba1768c
http://www.360doc.com/content/13/0717/16/2768962_300623597.shtml
http://www.latelee.org/programming-under-linux/linux-phy-driver.html
https://www.cnblogs.com/jason-lu/articles/3195473.html
http://blog.csdn.net/heli200482128/article/details/54091677
1.MAC和PHY硬件及接口协议
1.1网络硬件组成
网络有PHY,MAC和CPU组成。针对不同的组合形式可以有下面几种类型
方案一: CPU集成了MAC和PHY
方案二: CPU集成MAC,PHY采用独立芯片(3399是这种)
方案三: CPU不集成MAC与PHY,MAC与PHY采用集成芯片
由于在 RK 系列的 SoC 中内置了以太网 MAC 控制器,所以只需要搭配一颗以太网 PHY 芯片,
即可实现以太网卡功能。按照规范,即使是不同厂家的 PHY,仍然有一部分寄存器的定义是通用的,
只要配置了这些通用的寄存器,基本上 PHY 就可以正常工作。
1.2如何进行数据传输
在软件上网络的操作分为下面几步:
- 为数据收发分配内存
- 初始化MAC寄存器
- 初始化PHY寄存器
- 启动收发
1.3 MAC与PHY
收发数据这种耗时的事情,使用DMA是最合适的。CPU只需要告诉DMA起始地址和长度剩下的事情就可以自动完成,一般在MAC中有一组寄存器专门记录数据地址,cpu按照MAC的要求把数据放好后,启动MAC的数据发送就可以了
左边的连接在处理器上,右边的连接PHY芯片,MII DATA 与MIIM是与PHY进行数据传输和控制的
PHY芯片上的寄存器CPU不可以直接访问,只能通过MAC上的MIIM寄存器实现间接访问;右边就是我们的网口
1.4PHY与MAC之间的接口
RK3399使用的是RGMII,RGMII即Reduced GMII,是RGMII的简化版本,将接口信号线数量从24根减少到14根(COL/CRS端口状态指示信号,这里没有画出),时钟频率仍旧为125MHz,TX/RX数据宽度从8为变为4位,为了保持1000Mbps的传输速率不变,RGMII接口在时钟的上升沿和下降沿都采样数据。在参考时钟的上升沿发送GMII接口中的TXD[3:0]/RXD[3:0],在参考时钟的下降沿发送GMII接口中的TXD[7:4]/RXD[7:4]。RGMI同时也兼容100Mbps和10Mbps两种速率,此时参考时钟速率分别为25MHz和2.5MHz。另外,MDC和MDIO是MIIM(MII Management)用来配置PHY寄存器的
RGMII接口
2.驱动
PHY驱动phy_init //.\kernel\drivers\net\phy\phy_device.c mdio_bus_init class_register 在/sys/class/下创建mdio_bus bus_register 创建总线mdio_bus phy_drivers_register phy_driver_register 注册phy_driver new_driver->driver.name = new_driver->name; //可以搜索设备树中的这个名字 new_driver->driver.bus = &mdio_bus_type; new_driver->driver.probe = phy_probe; //当匹配成功回调用的函数 new_driver->driver.remove = phy_remove; driver_register(&new_driver->driver); //device_driver注册phy_driver注册成功了,等待phy_device的注册。根据测试发现phy_device的注册不依靠设备树(根据上面驱动的名字在设备树中搜不到),该设备的注册在后面的MDIO驱动中调用mdiobus_register中会注册phy_deviceMAC驱动 rk3399.dtsi gmac: ethernet@fe300000 { compatible = "rockchip,rk3399-gmac"; reg = <0x0 0xfe300000 0x0 0x10000>; rockchip,grf = <&grf>; interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH 0>; interrupt-names = "macirq"; clocks = <&cru SCLK_MAC>, <&cru SCLK_MAC_RX>, <&cru SCLK_MAC_TX>, <&cru SCLK_MACREF>, <&cru SCLK_MACREF_OUT>, <&cru ACLK_GMAC>, <&cru PCLK_GMAC>; clock-names = "stmmaceth", "mac_clk_rx", "mac_clk_tx", "clk_mac_ref", "clk_mac_refout", "aclk_mac", "pclk_mac"; resets = <&cru SRST_A_GMAC>; reset-names = "stmmaceth"; power-domains = <&power RK3399_PD_GMAC>; status = "disabled"; }; rk3399-firefly-linux.dts &gmac { phy-supply = <&vcc_phy>; //phy供电有&vcc_phy提供 phy-mode = "rgmii"; //rgmii 或 rmii clock_in_out = "input"; //时钟由PHY输入给MAC snps,reset-gpio = <&gpio3 15 GPIO_ACTIVE_LOW>; snps,reset-active-low; snps,reset-delays-us = <0 10000 50000>; assigned-clocks = <&cru SCLK_RMII_SRC>; //MAC的时钟源 assigned-clock-parents = <&clkin_gmac>; //MAC父时钟,下面再继续看 pinctrl-names = "default"; pinctrl-0 = <&rgmii_pins>; //必须和phy-mode一致 tx_delay = <0x28>; rx_delay = <0x11>; status = "okay"; }; clkin_gmac: external-gmac-clock { compatible = "fixed-clock"; clock-frequency = <125000000>; //125Mhz clock-output-names = "clkin_gmac"; #clock-cells = <0>; };E:\linux_kernel\hfs-workstation\rk3399-linux-origin-2017.4.5\kernel\drivers\net\ethernet\stmicro\stmmac\dwmac-rk.c通过上面的设备树成功匹配了平台设备module_platform_driver(rk_gmac_dwmac_driver)rk_gmac_probe of_device_get_match_data //返回的是匹配的of_device_id的data stmmac_get_platform_resources(pdev, &stmmac_res) //利用设备树中资源给stmmac_res赋值 stmmac_res->irq = platform_get_irq_byname(pdev, "macirq") //名字和设备树对应上 platform_get_resource //得到IORESOURCE_MEM资源,然后映射后填充到stmmac_res plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac) //填充plat_dat of_get_mac_address //得到mac地址 plat->interface = of_get_phy_mode(np) // 得到接口类型,设备树中是RGMII of_property_read_u32 //得到max speed ... //一些赋值 plat_dat->has_gmac = true; plat_dat->init = rk_gmac_init; //选择MAC与PHY通信接口(RGMII/GMII) plat_dat->exit = rk_gmac_exit; plat_dat->fix_mac_speed = rk_fix_speed; plat_dat->get_eth_addr = rk_get_eth_addr_vendor; rk_gmac_setup //分配填充bsp_priv然后放到plat_dat->bsp_priv bsp_priv = devm_kzalloc(dev, sizeof(*bsp_priv), GFP_KERNEL) //分配结构体 bsp_priv->phy_iface = of_get_phy_mode(dev->of_node) //接口类型RGMII of_property_read_string //和设备树对应上,给bsp_priv->clock_input = true; of_property_read_u32 //读取设备树“tx_delay”,bsp_priv->tx_delay = 0x28; of_property_read_u32 //读取设备树“rx_delay”,bsp_priv->rx_delay = 0x11; gmac_clk_init //配置了clk到bsp_priv rk_gmac_init //gmac初始化 bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay,bsp_priv->rx_delay) //rk_gmac_ops的set_to_rgmii方法 regmap_write // 写了几次寄存器 phy_power_on gmac_clk_enable pm_runtime_enable pm_runtime_get_sync stmmac_dvr_probe //E:\linux_kernel\hfs-workstation\rk3399-linux-origin-2017.4.5\kernel\drivers\net\ethernet\stmicro\stmmac\stmmac_main.c alloc_etherdev //分配net_device stmmac_set_ethtool_ops //设置了好多钩子函数 dev_set_drvdata //把priv->dev == device->driver_data stmmac_verify_args //合适一些驱动参数 stmmac_hw_init //初始化mac并且得到能力 ... stmmac_mdio_register //mdio bus 注册 mdiobus_alloc //分配一个mii_bus new_bus->read = &stmmac_mdio_read; //读取phy内部寄存器的数据 new_bus->write = &stmmac_mdio_write; //写phy内部寄存器的数据 new_bus->reset = &stmmac_mdio_reset; //重制MII总线 mdiobus_register //注册mii_bus device_register //注册设备文件 bus->reset(bus); //总线复位 mdiobus_scan //循环扫描phy设备 phydev = get_phy_device(bus, addr, false); //获取创建phy设备 err = phy_device_register(phydev); //注册phy设备 bus->state = MDIOBUS_REGISTERED; //状态设置为已注册 register_netdev //注册net_device,里面有个operations函数集合当执行ifconfig eth0 up 后,执行了E:\linux_kernel\hfs-workstation\rk3399-linux-origin-2017.4.5\kernel\drivers\net\ethernet\stmicro\stmmac\stmmac_main.c的stmmac_open函数,在执行后phy_drivers的probe函数才会执行stmmac_open stmmac_check_ether_addr //检查mac地址是否无效的 stmmac_init_phy //初始化phy phy_connect //连接ethernet设备和PHY设备 bus_find_device_by_name //从mdio总线上根据名字查找device to_phy_device //通过device得到phy_device phy_connect_direct //连接ethernet设备和特定的PHY设备 phy_attach_direct err = d->driver->probe(d); //phy_drivers的probe函数 device_bind_driver //绑定驱动到设备 phy_init_hw //(这里加了修改时钟的函数,硬件改了phy) phy_start_machine //启动PHY状态机 alloc_dma_desc_resources //分配TX/RX资源 init_dma_desc_rings //初始化RX/TX的回环描述 stmmac_hw_setup //设置mac为可用状态,配置mac核心寄存器,然后DMA数据准备接收和发送 phy_start //从新启动PHY设备
- phy子系统分析
- Linux网络子系统之---- PHY 配置
- Linux网络子系统之---- PHY 配置
- 以太网的phy寄存器分析
- 以太网的phy寄存器分析
- /drivers/net/phy/phy.c的状态机phy_state_machine分析
- PHY
- PHY
- PHY
- phy
- PHY芯片 AR8033驱动代码分析
- PHY芯片 AR8033驱动代码分析
- 输入子系统分析
- spi子系统分析
- spi子系统分析---续
- 输入子系统分析
- [转]输入子系统分析
- wifi子系统分析
- filter过滤器简单实例
- URL编码/解码
- 在python中,用plot绘制折线图
- 正则表达式(RegEx)
- java--面向对象之继承3
- phy子系统分析
- 查询linux的ftp的用户名和密码
- Netflix的设计微服务体系架构的最佳实践
- 21、访问者模式(Visitor)
- eclipse 配置连接hadoop集群
- idea+maven+ssm+shiro开发shiro权限登录,验证码
- 怎么和甲方交流
- 《C程序设计语言》【PDF】下载链接:
- LeetCode 26.Remove Duplicates from Sorted Array