FPGA Marvell 88exxxx phy 动起来

环境 
xilinx FPGA : Zynq or Kintex-7/Artix-7


方案 
驱动Marvell的Phy 正统套路是找marvell要芯片的手册 
但是不买上个千百片,人家Marvell可能不会理你 
零售代理商家可以提供么? 应该是有的


背景知识 
- - - 什么是MII、GMII、RGMII、SGMII、1000BaseX 
1. MII 的英文全称是 media-independent interface (MII) ,即介质独立接口 
初衷是为了当时的高速(百兆)以太网制定mac标准接口,由IEEE 802.3u工作组标准化 
采用“介质独立”接口的硬件,无论是双绞线还是光纤,都可以一视同仁,省去了更换的成本和麻烦 
2. 伴随MII接口的,是Management Data Input/Output (MDIO)串行控制总线,完成MAC和PHY的控制交互

为了适配不同的接口需求,扩展的MII接口形式如下 
reduced media-independent interface (RMII) 
gigabit media-independent interface (GMII) 
reduced gigabit media-independent interface (RGMII) 
serial gigabit media-independent interface (SGMII)


策略1:官方自测

1. 建立工程

手头利用vivado建立一个zynq的IPI工程,添加zynq PS,依靠自动生成功能补完最小系统,开始编译…… 
之后是export hdf—->generate SDK bsp的标准套路

值得记录的是Zynq的PS部分采用MIO和EMIO来复用有限的IO资源,这年头什么都是越来越软:软件定义XXX,软件无线电,HLS 
接口采用了MIO结构,也可以软件配置了

2. 外设自测

在生成的SDK中为外设建立一个自测: 
file–new–Application Project–standalone–peripheral test 
建好了的自测代码中,我们只关心核心的EMAC INIT部分

XEmacPs_SetMdioDivisor(EmacPsInstancePtr, MDC_DIV_224);if ((Platform & PLATFORM_MASK) == PLATFORM_SILICON) {EmacPsUtilEnterLoopback(EmacPsInstancePtr, EMACPS_LOOPBACK_SPEED_1G);XEmacPs_SetOperatingSpeed(EmacPsInstancePtr,EMACPS_LOOPBACK_SPEED_1G);} else {EmacPsUtilEnterLoopback(EmacPsInstancePtr, EMACPS_LOOPBACK_SPEED);XEmacPs_SetOperatingSpeed(EmacPsInstancePtr,EMACPS_LOOPBACK_SPEED);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

代码块做了三件事:为MDIO的mdc设置分频比、将PHY置为回环模式、设置工作速率 
不同版本的SDK生成的驱动也会有区别,在vivado新版sdk中,已经可以区分是marvell的phy还是TI的phy了

XEmacPs_PhyRead(EmacPsInstancePtr, PhyAddr, PHY_DETECT_REG1, &PhyIdentity);if (PhyIdentity == PHY_ID_MARVELL) {Status = EmacPsUtilMarvellPhyLoopback(EmacPsInstancePtr, Speed, PhyAddr);}if (PhyIdentity == PHY_ID_TI) {Status = EmacPsUtilTiPhyLoopback(EmacPsInstancePtr, Speed, PhyAddr);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

顺利的话,裸系统的代码可以辅助理解phy的驱动流程:写寄存器 
一般写pcore和写phy均会在驱动中涉及,具体定义参见相关手册 
值得记录的是,reg22为页寄存器:IEEE只给phy定义了32个寄存器空间,所以用其中一个寄存器来作为页寄存器,扩展维度 
流程参见自测,此处无必要详述

3. 外设再测

顺手可以在向导中生成一下标准平台的SDK工程: 
我选了个ZynqMP SOC的Lwip 

从Lwip的代码中找找eth的驱动


unsigned configure_IEEE_phy_speed(XAxiEthernet *xaxiemacp, unsigned speed)
{u16 control;u32 phy_addr = detect_phy(xaxiemacp);u16 phy_val;if (XAxiEthernet_GetPhysicalInterface(xaxiemacp) ==XAE_PHY_TYPE_RGMII_2_0) {/* Setting Tx and Rx Delays for RGMII mode */XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0x2);XAxiEthernet_PhyRead(xaxiemacp, phy_addr, IEEE_CONTROL_REG_MAC, &phy_val);phy_val |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_CONTROL_REG_MAC, phy_val);XAxiEthernet_PhyWrite(xaxiemacp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0x0);}XAxiEthernet_PhyRead(xaxiemacp, phy_addr,IEEE_CONTROL_REG_OFFSET,&control);control &= ~IEEE_CTRL_LINKSPEED_1000M;control &= ~IEEE_CTRL_LINKSPEED_100M;control &= ~IEEE_CTRL_LINKSPEED_10M;if (speed == 1000) {control |= IEEE_CTRL_LINKSPEED_1000M;}else if (speed == 100) {//...}//...}//此处有复位XAxiEthernet_PhyWrite(xaxiemacp, phy_addr,IEEE_CONTROL_REG_OFFSET,control | IEEE_CTRL_RESET_MASK);if (XAxiEthernet_GetPhysicalInterface(xaxiemacp) ==XAE_PHY_TYPE_SGMII) {//SGMII模式下的ISOLATE和自协商}{//等待配置结束volatile int wait;for (wait=0; wait < 100000; wait++);for (wait=0; wait < 100000; wait++);}return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

是不是很相似呢??其实完全一样么~~~ 
所以全都是一个套路呀


策略2:开源社区 
听说现在marvell的phy在petalinux的驱动上支持很完善

http://www.wiki.xilinx.com/PetaLinux

决定上开源社区去瞧一瞧 
去哪?当然是github 
啥啥都有,邓爷爷说的先富带动后富,开源精神vs拿来主义

https://github.com/Xilinx/linux-xlnx/blob/a96b8d2e1c9b37de51590b63bcce63a4036e760a/drivers/net/phy/marvell.c

linux采用devicetree来描述丰富的各类平台外设,具体啥是dts?水比较深 
引用一下相关学习地址:

http://www.wowotech.net/linux_kenrel/why-dt.html

回到正题,linux-xlnx分支下的phy配置结构,需要适配多种phy的特性,其配置做成了多层级适配的。即基本配置+特定phy的独立配置

这是核心基本配置的代码

/** Set and/or override some configuration registers based on the* marvell,reg-init property stored in the of_node for the phydev.** marvell,reg-init = <reg-page reg mask value>,...;** There may be one or more sets of <reg-page reg mask value>:** reg-page: which register bank to use.* reg: the register.* mask: if non-zero, ANDed with existing register value.* value: ORed with the masked value and written to the regiser.**/
static int marvell_of_reg_init(struct phy_device *phydev)
{const __be32 *paddr;int len, i, saved_page, current_page, page_changed, ret;if (!phydev->mdio.dev.of_node)return 0;paddr = of_get_property(phydev->mdio.dev.of_node,"marvell,reg-init", &len);if (!paddr || len < (4 * sizeof(*paddr)))return 0;saved_page = phy_read(phydev, MII_MARVELL_PHY_PAGE);if (saved_page < 0)return saved_page;page_changed = 0;current_page = saved_page;ret = 0;len /= sizeof(*paddr);for (i = 0; i < len - 3; i += 4) {u16 reg_page = be32_to_cpup(paddr + i);u16 reg = be32_to_cpup(paddr + i + 1);u16 mask = be32_to_cpup(paddr + i + 2);u16 val_bits = be32_to_cpup(paddr + i + 3);int val;if (reg_page != current_page) {current_page = reg_page;page_changed = 1;ret = phy_write(phydev, MII_MARVELL_PHY_PAGE, reg_page);if (ret < 0)goto err;}val = 0;if (mask) {val = phy_read(phydev, reg);if (val < 0) {ret = val;goto err;}val &= mask;}val |= val_bits;ret = phy_write(phydev, reg, val);if (ret < 0)goto err;}
err:if (page_changed) {i = phy_write(phydev, MII_MARVELL_PHY_PAGE, saved_page);if (ret == 0)ret = i;}return ret;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

通用的驱动会抽象一点,抽时间把驱动流程整理一下


引用wiki词条 Media-independent interface 
https://en.wikipedia.org/wiki/Media-independent_interface#Gigabit_Media_Independent_Interface

PS 常用phy寄存器


/* Advertisement control register. */
#define ADVERTISE_10HALF    0x0020  /* Try for 10mbps half-duplex  */
#define ADVERTISE_1000XFULL 0x0020  /* Try for 1000BASE-X full-duplex */
#define ADVERTISE_10FULL    0x0040  /* Try for 10mbps full-duplex  */
#define ADVERTISE_1000XHALF 0x0040  /* Try for 1000BASE-X half-duplex */
#define ADVERTISE_100HALF   0x0080  /* Try for 100mbps half-duplex */
#define ADVERTISE_1000XPAUSE    0x0080  /* Try for 1000BASE-X pause    */
#define ADVERTISE_100FULL   0x0100  /* Try for 100mbps full-duplex */
#define ADVERTISE_1000XPSE_ASYM 0x0100  /* Try for 1000BASE-X asym pause */
#define ADVERTISE_100BASE4  0x0200  /* Try for 100mbps 4k packets  */#define ADVERTISE_100_AND_10    (ADVERTISE_10FULL | ADVERTISE_100FULL | \ADVERTISE_10HALF | ADVERTISE_100HALF)
#define ADVERTISE_100       (ADVERTISE_100FULL | ADVERTISE_100HALF)
#define ADVERTISE_10        (ADVERTISE_10FULL | ADVERTISE_10HALF)#define ADVERTISE_1000      0x0300#define IEEE_CONTROL_REG_OFFSET                 0
#define IEEE_STATUS_REG_OFFSET                  1
#define IEEE_AUTONEGO_ADVERTISE_REG             4
#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET     5
#define IEEE_PARTNER_ABILITIES_2_REG_OFFSET     8
#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET     10
#define IEEE_1000_ADVERTISE_REG_OFFSET          9
#define IEEE_MMD_ACCESS_CONTROL_REG             13
#define IEEE_MMD_ACCESS_ADDRESS_DATA_REG        14
#define IEEE_COPPER_SPECIFIC_CONTROL_REG        16
#define IEEE_SPECIFIC_STATUS_REG                17
#define IEEE_COPPER_SPECIFIC_STATUS_REG_2       19
#define IEEE_EXT_PHY_SPECIFIC_CONTROL_REG       20
#define IEEE_CONTROL_REG_MAC                    21
#define IEEE_PAGE_ADDRESS_REGISTER              22#define IEEE_CTRL_1GBPS_LINKSPEED_MASK          0x2040
#define IEEE_CTRL_LINKSPEED_MASK                0x0040
#define IEEE_CTRL_LINKSPEED_1000M               0x0040
#define IEEE_CTRL_LINKSPEED_100M                0x2000
#define IEEE_CTRL_LINKSPEED_10M                 0x0000
#define IEEE_CTRL_RESET_MASK                    0x8000
#define IEEE_CTRL_AUTONEGOTIATE_ENABLE          0x1000
#define IEEE_STAT_AUTONEGOTIATE_CAPABLE         0x0008
#define IEEE_STAT_AUTONEGOTIATE_COMPLETE        0x0020
#define IEEE_STAT_AUTONEGOTIATE_RESTART         0x0200
#define IEEE_STAT_1GBPS_EXTENSIONS              0x0100
#define IEEE_AN1_ABILITY_MASK                   0x1FE0
#define IEEE_AN3_ABILITY_MASK_1GBPS             0x0C00
#define IEEE_AN1_ABILITY_MASK_100MBPS           0x0380
#define IEEE_AN1_ABILITY_MASK_10MBPS            0x0060
#define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK      0x0030#define IEEE_ASYMMETRIC_PAUSE_MASK              0x0800
#define IEEE_PAUSE_MASK                         0x0400
#define IEEE_AUTONEG_ERROR_MASK                 0x8000#define IEEE_MMD_ACCESS_CTRL_DEVAD_MASK         0x1F
#define IEEE_MMD_ACCESS_CTRL_PIDEVAD_MASK       0x801F
#define IEEE_MMD_ACCESS_CTRL_NOPIDEVAD_MASK     0x401F#define PHY_R0_ISOLATE                          0x0400
#define PHY_DETECT_REG                          1
#define PHY_IDENTIFIER_1_REG                    2
#define PHY_IDENTIFIER_2_REG                    3
#define PHY_DETECT_MASK                         0x1808
#define PHY_MARVELL_IDENTIFIER                  0x0141
#define PHY_TI_IDENTIFIER                       0x2000/* Marvel PHY flags */
#define MARVEL_PHY_IDENTIFIER                   0x141
#define MARVEL_PHY_MODEL_NUM_MASK               0x3F0
#define MARVEL_PHY_88E1111_MODEL                0xC0
#define MARVEL_PHY_88E1116R_MODEL               0x240
#define PHY_88E1111_RGMII_RX_CLOCK_DELAYED_MASK 0x0080

FPGA Marvell 88exxxx phy 动起来相关推荐

  1. 一文读懂如何使用FPGA驱动PHY芯片

    这里写自定义目录标题 如何使用FPGA驱动PHY芯片 前言 必要的硬件知识 如何确定PHY芯片的物理地址? 如何确定PHY芯片的工作模式? 如何驱动PHY芯片? MDIO的通讯协议是什么? PHY芯片 ...

  2. Network 之二 Ethernet(以太网)中的 MAC、MII、PHY 详解

    结构   从硬件的角度看,以太网接口电路主要由 MAC(Media Access Control,MAC)控制器和物理层接口 PHY(Physical Layer,PHY)两大部分构成.如下图所示: ...

  3. 转载:网口扫盲三:以太网芯片MAC和PHY的关系

    原文地址:http://www.cnblogs.com/jason-lu/articles/3195473.html 问:如何实现单片以太网微控制器? 答:诀窍是将微控制器.以太网媒体接入控制器(MA ...

  4. Ethernet(以太网) 详解 MAC、MII、PHY

    Ethernet(以太网) 详解 MAC.MII.PHY 结构   从硬件的角度看,以太网接口电路主要由MAC(Media Access Control)控制器和物理层接口PHY(Physical L ...

  5. 以太网芯片MAC和PHY

    网口扫盲三:以太网芯片MAC和PHY的关系 问:如何实现单片以太网微控制器? 答:诀窍是将微控制器.以太网媒体接入控制器(MAC)和物理接口收发器(PHY)整合进同一芯片,这样能去掉许多外接元器件.这 ...

  6. 以太网芯片mac/phy的关系

    问:如何实现单片以太网微控制器? 答:诀窍是将微控制器.以太网媒体接入控制器(MAC)和物理接口收发器(PHY)整合进同一芯片,这样能去掉许多外接元器件.这种方案可使MAC和PHY实现很好的匹配,同时 ...

  7. 以太网PHY寄存器分析

    以太网PHY寄存器分析    1 1.以太网PHY标准寄存器分析    2 1.1 Control Register    2 1.2 Status register    5 1.3 PHY Ide ...

  8. Mstar Mac Phy 驱动学习

    MII.h 和 MII.c 这是MII协议.里面有MII协议的PHY寄存器地址,及MII通信接口库 Linux的mdio主要是为了管理PHY芯片寄存器的,跟踪代码发现,它会进行创建PHY设备及一些初始 ...

  9. FPGA通信第二篇--UDP

    FPGA通信第二篇–UDP 本文通过对以太网通信中的UDP传输协议的理论学习,针对UDP实际应用中的丢包问题,提出一种人为的重发机制完成UDP稳定可靠的传输,并通过实验进行了验证. 1 以太网简介 以 ...

  10. 一文读懂嵌入式FPGA,改变芯片设计方式岂是闹着玩的

    芯片设计人员今天面临的最关键的问题之一是在设计过程中实时重新配置RTL,甚至在系统中也是如此.不幸的是,芯片设计人员无法及时知道是否必须这样做.在这一点上,任何变化都会花费数百万美元,并将项目推迟数月 ...

最新文章

  1. 独家|OpenCV1.11 使用OpenCV制作一个低成本立体摄像机
  2. MySQL数据库:读写分离
  3. 游戏行业的人工智能设计:AI的设计和实施
  4. JVM系列之:从汇编角度分析NullCheck
  5. 会话的清除与建立网络磁盘
  6. 页面缓存处理的几种方法
  7. 深入浅出 Java CMS 学习笔记
  8. c#设计12星座速配软件_C#设计模式(12)——组合模式
  9. Windows Live Messenger 新功能预览
  10. 设计灵感|纯文字排版也能让海报引人注目
  11. Microsoft caffe cifar实例编译之model的生成
  12. 特殊字符是哪些字符python_python特殊字符
  13. java spy_Java Spy - 代码跟踪神器
  14. 笔记本电脑插入HDMI外接显示器没有声音问题
  15. 利用PicGo快速获得图片外链(七牛云图床)
  16. Oracle的LAST_DAY函数
  17. 7-4 最短路径之Dijkstra(朴素dijkstra打印路径)
  18. sql server 2014 使用sql清理日志(简单方便)
  19. stm32h750/stm32h743原理图和pcb源文件
  20. 谢处方电磁场与电磁波第4版课后答案

热门文章

  1. 计算机黑龙江省二级c语言题库,计算机二级c语言题库
  2. python 文本转excel_如何使用python将txt文件中的数据转换为Excel文件
  3. [译]记一次Kotlin官方文档翻译的PR(内联类)
  4. QT5编程入门教程(非常详细)
  5. java9最新下载_java9下载_java9官方版下载 32位64位 最新版_天天下载手机版
  6. 计算机组成原理--白中英版 全部知识点
  7. Matlab运行程序_暂停方法
  8. AI的委屈只有它知道……
  9. Ubuntu/Linux备份/还原系统
  10. java核心技术.pdf