目录
1.PHY芯片介绍
1.1 芯片引脚定义和说明
1.2 PHY芯片功能说明
1.3 供电管理
1.4 寄存器说明
1.4.1 控制寄存器
1.4.2 状态寄存器
1.4.3 PHY ID寄存器
1.4.4 自协商广播寄存器
1.4.5 自动协商链接合作伙伴能力寄存器
1.4.6 自动协商扩展寄存器
1.4.7 AVICOM指定的配置寄存器
1.4.8 DAVICOM指定的配置和状态寄存器
1.4.9 10BASE-T配置/状态
1.4.10 掉电控制寄存器
1.4.11 其他寄存器
2.PHY编程说明
2.1 phy_def.h
2.2 phy.h
2.3 phy.c
PHY供电口
MII RMII GMII 引脚MAP
MII引脚
状态模式显示
外部收发差分接口
LED接口,用于驱动网线口灯
另外LED口复用选择了Media的类型
MII接口说明
TXD(传输数据)是半字节(4位)的数据,由和解子层相对于TXCLK同步驱动。 对于每个TXCLK周期,TXEN被声明,TXD(3:0)被接受由PHY传输。
TXCLK(发送时钟)输出到MAC协调表子层是提供时序的连续时钟TXEN,TXD和TXER传输的参考信号。
TXEN 从MAC协调子层输入的TXEN(发送使能)指示在MII上存在半字节以在物理介质上进行传输
TXER(发送编码错误)转换相对于TXCLK是同步的。 如果在一个或多个时钟周期内断言了TXER,并且断言了TXEN,则PHY将发出一个或多个符号,这些符号不属于正在传输的帧中某处设置的有效数据定界符。
CRS 当发送或接收介质为非空闲时,PHY会声明CRS(载波侦听),而当发送和接收介质处于空闲状态时,会由PHY取消声明CRS(载波侦听)。 图7-2描述了10Base-T和100Base-TX传输期间CRS的行为。
针对RX,同TX,不做过多说明。
信号检测电路始终打开,以监视介质上是否有任何信号。 如果电缆断开连接,DM9161A将自动关闭电源并进入省电模式,无论其操作模式是N向自动协商还是强制模式。 在省电模式下,发送电路将以最小的功耗继续发送快速链接脉冲。 如果从介质中检测到有效信号(可能是N路快速链接脉冲,10Base-T常规链接脉冲或100Base-TX MLT3信号),则设备将唤醒并恢复正常操作模式。
可以通过将Reg.16.4写入零来禁用自动降低功耗模式
通过将Reg.0.11设置为1 或将PWRDWN引脚拉高,可以进入掉电模式,这将禁用所有发送和接收功能以及MDC / MDIO管理接口以外的MII接口功能。
通过在其TX侧设计1.25:1匝数比磁通,并在BGRES和BGRESG引脚上使用8.5KΩ电阻,以及将TX + / TX-拉高电阻从50Ω变为78Ω,可以进一步降低发射功率。 这种配置可以减少约20%的发射功率。
DM9161A支持自动检测电缆连接类型,当设置为自动时,由16位LFSR产生MDI / MDIX控制时序的极性。 开关周期时间从200ms到420ms。 极性控制始终处于切换状态,直到检测到接收到的信号为止。 选择MDI或MDIX之后,可以通过寄存器位(20.7)读取极性状态。
寄存器说明部分,可以通过英文解释了解,其中中文部分,部分参考 https://blog.csdn.net/ZCShouCSDN/article/details/80090802,方便理解。
Reset
通过将位0.15设置为逻辑1来完成复位PHY。 该操作应将状态和控制寄存器设置为其默认状态。 因此,此操作可能会改变PHY的内部状态以及与PHY关联的物理链路的状态。复位过程中Bit15保持为1,复位完成之后该位应该自动清零。 在复位过程完成之前,PHY不需要接受对控制寄存器的写入操作,并且在复位过程完成之前写入0.15以外的控制寄存器位可能不起作用。 复位过程应在0.15位设置的0.5 s内完成。
(1)一般要改变端口的工作模式(如速率、双工、流控或协商信息等)时,在设置完相应位置的寄存器之后,需要通过Reset位复位PHY来使配置生效。
(2)该比特位的默认值为 0。
Loopback
当位0.14被设置为逻辑1时,PHY应置于环回操作模式。 当位0.14置位时,PHY接收电路应与网络介质隔离,并且MII或GMII处的TX_EN断言不应导致网络介质上的数据传输。 当位0.14置位时,PHY应接受来自MII或GMII发送数据路径的数据,并将其返回给MII或GMII接收数据路径,以响应TX_EN的断言。 当位0.14置位时,从断言TX_EN到断言RX_DV的延迟应小于512 BT。 当位0.14置位时,除非设置了位0.7,否则COL信号应始终保持无效,在这种情况下,COL信号的行为应如22.2.4.1.9所述。 清0.14位为零允许正常操作。
Loopback是一个调试以及故障诊断中常用的功能,Bit14置1之后,PHY和外部MDI的连接在逻辑上将被断开,从MAC经过MII/GMII(也可能是其他的MAC/PHY接口)发送过来的数据将不会被发送到MDI上,而是在PHY内部(一般在PCS)回环到本端口的MII/GMII接收通道上,通过Loopback功能可以检查MII/GMII以及PHY接口部分是否工作正常,对于端口不通的情况可用于故障定位。
(1)需要注意的是,很多时候PHY设置Loopback后端口可能就Link down了,MAC无法向该端口发帧,这时就需要通过设置端口Force Link up才能使用Loopback功能。
(2)该比特位的默认值为 0。
Speed Selection
Bit13和Bit6两位联合实现对端口的速率控制功能。链接速度可以通过自动协商过程或手动速度选择来选择。 通过将位0.12清零来禁用自动协商时,允许手动速度选择。
当禁用自动协商并将位0.6清除为逻辑0时,将位0.13设置为逻辑1将PHY配置为100 Mb / s操作,并将位0.13清除为逻辑0将PHY配置为10 Mb / s操作 。
当禁用自动协商并将位0.6设置为逻辑1时,将位0.13清零为逻辑0会选择1000 Mb / s的操作。 将位0.6和0.13设置为逻辑1的组合保留用于未来的标准化。
当使能自动协商时,可以读取或写入位0.6和0.13,但位0.6和位0.13的状态对链路配置没有影响,位0.6和位0.13不需要反映当它被读取时链接。如果PHY通过比特1.15:9和比特15.15:12报告它不能工作在所有速度时,则比特0.6和0.13的值应该与PHY可以操作的速度相对应。并且任何试图将该位设置为无效的操作均将被忽略。
(1)对Speed Selection的修改设置,往往需要复位端口才能配置生效。因此在设置该位置的时候需要检查自动协商的设置并通过Bit15复位端口。
(2)位0.6和0.13的默认值是根据位1.15:9和15.15:12所指示的PHY可以操作的***最高数据速率***的编码组合。
Auto-Negotiation Enable
自动协商过程应通过将位0.12设置为逻辑1来启用。 如果位0.12设置为逻辑1,则位0.13、0.8和0.6不应对链路配置和除了自动协商协议规定之外的站操作产生影响。 如果将位0.12清零为逻辑0,则无论链路配置和自动协商过程的先前状态如何,位0.13、0.8和0.6都将确定链路配置。如果PHY通过位1.3报告它缺乏执行自动协商的能力,则PHY应在位0.12返回零值。 如果PHY通过位1.3报告它缺乏执行自动协商的能力,则位0.12应该始终写为0,并且任何尝试将1写入位0.12都应该被忽略。必须注意的是,对于1000BASE-T接口,自动协商必须打开。
Power Down
通过将位0.11设置为逻辑1,可以将PHY置于低功耗状态。 清0.11位为零允许正常操作。 PHY在掉电状态下的具体行为是特定实现的。 处于掉电状态时,PHY应响应管理事务。 在转换到掉电状态期间和处于掉电状态期间,PHY不应在MII或GMII上产生寄生信号。
当位0.11或位0.10被设置为逻辑1时,PHY不需要满足RX_CLK和TX_CLK信号功能要求。 在位0.11和0.10清零后,PHY应在0.5 s内满足22.2.2中定义的RX_CLK和TX_CLK信号功能要求。
(1)Power Down模式一般在软件shut down端口的时候使用,需要注意的是端口从Power Down模式恢复,需要复位端口以保证端口可靠的连接。
(2)该位的默认值为 0。
Isolate
通过将位0.10设置为逻辑1,PHY可能被迫将其数据路径与MII或GMII电隔离。 清零位0.10允许正常操作。 当PHY与MII或GMII隔离时,它不会响应TXD数据包和TX_EN,TX_ER、GTX_CLK的输入。并且它的TX_CLK,RX_CLK,RX_DV,RX_ER,RXD数据包、COL和CRS输出均应为高阻态。 当PHY与MII或GMII隔离时,它将响应管理事务(MDC/MDIO接口的信号)。
(1)IEEE802.3没有对Isolate 时MDI接口的状态进行规范,此时MDI端可能还在正常运行。Isolate在实际应用中并没有用到。
(2)由于目前很多百兆的PHY芯片其MAC接口主流的都是SMII/S3MII,8个端口的接口是相互关联的,一个端口设置Isolate可能会影响其他端口的正常使用,因此在使用中注意不要随意更改bit10的状态。
Restart Auto-Negotiation
如果PHY通过位1.3报告它缺乏执行自动协商的能力,或者如果自动协商被禁用,则PHY应在位0.9返回零值。 如果PHY通过位1.3报告它缺乏执行自动协商的能力,或者如果禁用了自动协商,则应将位0.9始终写为0,并且任何尝试将1写入位0.9应被忽略。Bit9置1将重新启动端口的自动协商进程,当然前提是Auto-Negotiation Enable是使能的。一般在修改端口的自动协商能力信息之后通过Bit9置1重新启动自动协商来使端口按照新的配置建立link。
Duplex Mode
可以通过自动协商过程或手动双面选择来选择双工模式。 通过将位0.12清零来禁用自动协商时,允许手动双面选择。
当禁用自动协商时,将位0.8设置为逻辑1将PHY配置为全双工操作,并将位0.8清零以将逻辑0配置为用于半双工操作的PHY。
当启用自动协商时,可以读取或写入位0.8,但位0.8的状态对链路配置没有影响。如果PHY通过位1.15:9和15.15:12报告它只能在一个双工模式下工作,则位0.8的值应该与PHY可以工作的模式相对应,并且任何尝试改变将该位0.8修改为无效指的操作应被忽略。对Duplex Mode的修改配置也需要复位端口才能生效。
Collision Test
冲突信号(COL)测试开关。在需要对COL信号进行测试时,可以通过Bit7置1,这时PHY将输出一个COL脉冲以供测试。实际测试操作中也可以将端口配置为半双工状态,通过发帧冲突来测试COL信号,因此该配置实用价值不大。
Unidirectional enable
如果PHY通过比特1.7报告它不具备编码和传输来自媒体独立接口的数据的能力,而不管PHY是否确定已建立有效链路,则PHY应在比特0.5中返回零值,并且 任何尝试写一个到位0.5应该被忽略。
100BASE-T4 ability
当读为逻辑1时,位1.15指示PHY有能力使用100BASE-T4信令规范执行链路发送和接收。 当读为逻辑0时,位1.15表示PHY缺乏使用100BASE-T4信令规范执行链路发送和接收的能力。
100BASE-X full duplex ability
当读为逻辑1时,位1.14指示PHY有能力使用100BASE-X信令规范执行全双工链路传输和接收。 当作为逻辑0读取时,bit1.14表示PHY缺乏使用100BASE-X信令规范执行全双工链路传输和接收的能力。
100BASE-X half duplex ability
当读为逻辑1时,位1.13指示PHY有能力使用100BASE-X信令规范执行半双工链路传输和接收。 当读为逻辑0时,位1.13指示PHY缺乏使用100BASE-X信令规范执行半双工链路传输和接收的能力。
其他同类型的值意义基本与上面几个相同:指示PHY所具有的工作模式能力,不再一一说明。
Unidirectional ability
当读为逻辑1时,位1.7指示PHY具有编码和传输来自媒体独立接口的数据的能力,而不管PHY是否确定已建立有效链路。 当读为逻辑0时,位1.7指示PHY只有在PHY确定已建立有效链路时才能从媒体独立接口传输数据。
MF preamble suppression ability
当读为逻辑1时,位1.6指示PHY能够接受管理帧,而不管它们是否在22.2.4.5.2中描述的前导码模式之前。 当读为逻辑0时,位1.6指示PHY不能接受管理帧,除非它们之前是22.2.4.5.2中描述的前导码模式。
Auto-Negotiation Complete
当读为逻辑1时,位1.5指示自动协商过程已完成,并且由自动协商协议(条款28或条款37)实施的扩展寄存器的内容是有效的。 当读为逻辑0时,位1.5指示自动协商过程尚未完成,并且扩展寄存器的内容由自动协商协议的当前状态定义,或者为手动配置写入。 如果自动协商通过清除位0.12禁用,则PHY应在位1.5返回零值。 如果PHY缺乏执行自动协商的能力,它还应在位1.5返回零值。
在调试以及异常故障处理时,可以通过该位寄存器的状态判断AN是否成功,从而进一步的检查AN相关的设置是否正确,或者芯片的AN功能是否正常等。
Remote Fault
当读为逻辑1时,位1.4表示检测到远程故障状态。 故障类型以及故障检测的标准和方法是PHY特定的。 远程故障位必须使用锁存功能来实现,以便发生远程故障将导致远程故障位置位,并保持置位状态直至被清除。 每当通过管理接口读取寄存器1时,远程故障位应清零,并且还应通过PHY复位清零。
远端错误指示位。Bit4=1代表连接对端(Link Partner)出错,至于出错的具体类型以及错误检测机制在规范中并没有定义,由PHY的制造商自由发挥,一般的厂商都会在其他的寄存器(Register16-31由厂商自行定义)指示比较详细的错误类型。在与端口相关的故障查证中,Remote Fault是一个重要的指示信息,通过互联双方的Remote Fault信息(可能要加上其他的具体错误指示),可以帮助定位故障原因。
Auto-Negotiation ability
当读为逻辑1时,位1.3指示PHY有能力执行自动协商。 当读为逻辑0时,位1.3指示PHY缺乏执行自动协商的能力。
Link Status: 当读为逻辑1时,位1.2指示PHY已经确定已建立有效链路。 当作为逻辑0读取时,位1.2指示该链接无效。 确定链路有效性的标准是PHY特定的。 链路状态位应该使用锁存功能来实现,以便发生链路故障情况将导致链路状态位清零并保持清零,直到通过管理接口读取。 此状态指示旨在支持在30.5.1.1.4,aMediaAvailable中定义的管理属性。
实际应用中一般都是通过Bit2来判断端口的状态。而且,一般的MAC芯片也是通过轮询PHY的这个寄存器值来判断端口的Link状态的(这个过程可能有不同的名称,比如BCM叫做Link Scan,而Marvell叫做PHY Polling。)如前所述,在AN Enable的情况下,Link Status的信息只有在Auto-Negotiation Complete指示已经完成的情况下才是正确可靠的,否则有可能出错。
Jabber Detect: 当作为逻辑1读取时,位1.1指示已经检测到爆音条件。 此状态指示旨在支持30.5.1.1.6中定义的管理属性,aJabber和30.5.1.3.1 nJabber中定义的MAU通知。 检测Jabber条件的标准是PHY特定的。 Jabber检测位应该使用锁存功能来实现,以便发生Jabber条件将导致Jabber检测位置位,并保持置位状态直至被清除。 每次通过管理接口读取寄存器1时,Jabber检测位应清零,并且还应通过PHY复位清零。
IEEE802.3对Jabber的解释是“A condition wherein a station transmits for a period of time longer than the maximum permissible packet length, usually due to a fault condition”。这一位指示的是Link Partner发送的时间超过了规定的最大长度。值得注意的是,Jabber Detect只有在10BASE-T模式下才有意义,100和1000M模式是没有定义Jabber这一功能的。
不做过多解释
该寄存器包含此DM9161A设备的广播(广告)能力,因为它们将在自动协商期间传输到其链接伙伴
这里主要注意速度的选择
选择工作模式,全双工 半双工
#ifndef NET_PHY_DEF_MODULE_PRESENT
#define NET_PHY_DEF_MODULE_PRESENT
#define NET_PHY_SPD_0 0 /* Link speed unknown, or link down */
#define NET_PHY_SPD_10 10 /* Link speed = 10mbps */
#define NET_PHY_SPD_100 100 /* Link speed = 100mbps */
#define NET_PHY_SPD_1000 1000 /* Link speed = 1000mbps */
#define NET_PHY_DUPLEX_UNKNOWN 0 /* Duplex uknown or auto-neg incomplete */
#define NET_PHY_DUPLEX_HALF 1 /* Duplex = Half Duplex */
#define NET_PHY_DUPLEX_FULL 2 /* Duplex = Full Duplex */
#define NET_PHY_ERR_NONE 12000
#endif
#ifndef _NET_PHY_H
#define _NET_PHY_H
/*
*****************************************************************************************
* INCLUDES
*****************************************************************************************
*/
/*
*****************************************************************************************
* DEFINES
*****************************************************************************************
*/
#define DM9161AE_INIT_AUTO_NEG_RETRIES 3
#define DM9161AE_OUI 0x00606E
#define DM9161AE_VNDR_MDL 0x08
/*
*****************************************************************************************
* DM9161AE REGISTER DEFINES
*****************************************************************************************
*/
/* ------- Generic MII registers ---------- */
#define MII_BMCR 0x00 /* Basic mode control register */
#define MII_BMSR 0x01 /* Basic mode status register */
#define MII_PHYSID1 0x02 /* PHYS ID 1 */
#define MII_PHYSID2 0x03 /* PHYS ID 2 */
#define MII_ANAR 0x04 /* Advertisement control reg */
#define MII_ANLPAR 0x05 /* Link partner ability reg */
#define MII_ANER 0x06 /* Expansion register */
/* ---------- Extended registers ---------- */
#define DM9161_DSCR 0x10 /* DAVICOM specified configuration */
#define DM9161_DSCSR 0x11 /* DAVICOM specified configuration & status */
#define DM9161_PWDOR 0x13 /* Power down control register */
#define DM9161_SCR 0x14 /* Specified configuration */
#define DM9161_MDINTR 0x15 /* DAVICOM Specified interrupt register */
#define DM9161_RECR 0x16 /* DAVICOM specified RX error counter reg. */
#define DM9161_DISCR 0x17 /* DAVICOM specified disconnect cntr. reg. */
#define DM9161_RLSR 0x18 /* DAVICOM hardware reset latch state reg. */
/*
*****************************************************************************************
* DM9161AE REGISTER BITS
*****************************************************************************************
*/
/* -------- MII_BMCR Register Bits -------- */
#define BMCR_RESV 0x007F /* Unused... */
#define BMCR_CTST DEF_BIT_07 /* Collision test */
#define BMCR_FULLDPLX DEF_BIT_08 /* Full duplex */
#define BMCR_ANRESTART DEF_BIT_09 /* Auto negotiation restart */
#define BMCR_ISOLATE DEF_BIT_10 /* Disconnect DP83840 from MII */
#define BMCR_PDOWN DEF_BIT_11 /* Powerdown the DP83840 */
#define BMCR_ANENABLE DEF_BIT_12 /* Enable auto negotiation */
#define BMCR_SPEED100 DEF_BIT_13 /* Select 100Mbps */
#define BMCR_LOOPBACK DEF_BIT_14 /* TXD loopback bits */
#define BMCR_RESET DEF_BIT_15 /* Reset the DP83840 */
/* -------- MII_BMSR Register Bits -------- */
#define BMSR_ERCAP DEF_BIT_00 /* Ext-reg capability */
#define BMSR_JCD DEF_BIT_01 /* Jabber detected */
#define BMSR_LSTATUS DEF_BIT_02 /* Link status */
#define BMSR_ANEGCAPABLE DEF_BIT_03 /* Able to do auto-negotiation */
#define BMSR_RFAULT DEF_BIT_04 /* Remote fault detected */
#define BMSR_ANEGCOMPLETE DEF_BIT_05 /* Auto-negotiation complete */
#define BMSR_RESV 0x07C0 /* Unused... */
#define BMSR_10HALF DEF_BIT_11 /* Can do 10mbps, half-duplex */
#define BMSR_10FULL DEF_BIT_12 /* Can do 10mbps, full-duplex */
#define BMSR_100HALF DEF_BIT_13 /* Can do 100mbps, half-duplex */
#define BMSR_100FULL DEF_BIT_14 /* Can do 100mbps, full-duplex */
#define BMSR_100BASE4 DEF_BIT_15 /* Can do 100mbps, 4k packets */
/* -------- MII_ANAR Register Bits -------- */
#define ANAR_SLCT 0x001F /* Selector bits */
#define ANAR_CSMA DEF_BIT_04 /* Only selector supported */
#define ANAR_10HALF DEF_BIT_05 /* Try for 10mbps half-duplex */
#define ANAR_10FULL DEF_BIT_06 /* Try for 10mbps full-duplex */
#define ANAR_100HALF DEF_BIT_07 /* Try for 100mbps half-duplex */
#define ANAR_100FULL DEF_BIT_08 /* Try for 100mbps full-duplex */
#define ANAR_100BASE4 DEF_BIT_09 /* Try for 100mbps 4k packets */
#define ANAR_RESV 0x1C00 /* Unused... */
#define ANAR_RFAULT DEF_BIT_13 /* Say we can detect faults */
#define ANAR_LPACK DEF_BIT_14 /* Ack link partners response */
#define ANAR_NPAGE DEF_BIT_15 /* Next page bit */
#define ANAR_FULL (ANAR_100FULL | ANAR_10FULL | ANAR_CSMA)
#define ANAR_ALL (ANAR_100FULL | ANAR_10FULL | ANAR_100HALF | ANAR_10HALF)
/* ------- MII_ANLPAR Register Bits ------- */
#define ANLPAR_SLCT 0x001F /* Same as advertise selector */
#define ANLPAR_10HALF DEF_BIT_05 /* Can do 10mbps half-duplex */
#define ANLPAR_10FULL DEF_BIT_06 /* Can do 10mbps full-duplex */
#define ANLPAR_100HALF DEF_BIT_07 /* Can do 100mbps half-duplex */
#define ANLPAR_100FULL DEF_BIT_08 /* Can do 100mbps full-duplex */
#define ANLPAR_100BASE4 DEF_BIT_09 /* Can do 100mbps 4k packets */
#define ANLPAR_RESV 0x1C00 /* Unused... */
#define ANLPAR_RFAULT DEF_BIT_13 /* Link partner faulted */
#define ANLPAR_LPACK DEF_BIT_14 /* Link partner acked us */
#define ANLPAR_NPAGE DEF_BIT_15 /* Next page bit */
#define ANLPAR_DUPLEX (ANLPAR_10FULL | ANLPAR_100FULL)
#define ANLPAR_100 (ANLPAR_100FULL | ANLPAR_100HALF | ANLPAR_100BASE4)
/* -------- MII_ANER Register Bits -------- */
#define ANER_NWAY DEF_BIT_00 /* Can do N-way auto-nego */
#define ANER_LCWP DEF_BIT_01 /* Got new RX page code word */
#define ANER_ENABLENPAGE DEF_BIT_02 /* This enables npage words */
#define ANER_NPCAPABLE DEF_BIT_03 /* Link partner supports npage */
#define ANER_MFAULTS DEF_BIT_04 /* Multiple faults detected */
#define ANER_RESV 0xFFE0 /* Unused... */
/* ------ DM9161_MDINTR Register Bits ----- */
#define MDINTR_INTR_PEND DEF_BIT_15 /* Interrupt pending */
#define MDINTER_FDX_MSK DEF_BIT_11 /* Full-duplex interrupt mask */
#define MDINTER_SPD_MSK DEF_BIT_10 /* Speed interrupt mask */
#define MDINTER_LINK_MSK DEF_BIT_09 /* Link interrupt mask */
#define MDINTER_INTR_MSK DEF_BIT_08 /* Master interrupt mask */
#define MDINTER_FDX_CHG DEF_BIT_04 /* Full-duplex change */
#define MDINTER_SPD_CHG DEF_BIT_03 /* Speed change */
#define MDINTER_LINK_CHG DEF_BIT_02 /* Link change */
#define MDINTER_INTR_STAT DEF_BIT_00 /* Interrupt status */
/*
*****************************************************************************************
* PHY ERROR CODES 12,000 -> 13,000
*****************************************************************************************
*/
#define NET_PHY_ERR_REGRD_TIMEOUT 12010
#define NET_PHY_ERR_REGWR_TIMEOUT 12020
#define NET_PHY_ERR_AUTONEG_TIMEOUT 12030
/*
*****************************************************************************************
* FUNCTION PROTOTYPES
*****************************************************************************************
*/
void NetNIC_PhyInit (NET_ERR *perr);
void NetNIC_PhyAutoNeg (void); /* Do link auto-negotiation */
#if (EMAC_CFG_PHY_INT == DEF_ON)
void NetNIC_PhyISR_Handler (void); /* Decode & handle PHY ISRs. */
#endif
/* -----------------PHY STATUS FNCTS ------------------ */
CPU_BOOLEAN NetNIC_PhyAutoNegState (void); /* Get PHY auto-negotiation state */
CPU_BOOLEAN NetNIC_PhyLinkState (void); /* Get PHY link state */
CPU_INT32U NetNIC_PhyLinkSpeed (void); /* Get PHY link speed */
CPU_INT32U NetNIC_PhyLinkDuplex (void); /* Get PHY duplex mode */
/*
*****************************************************************************************
* FUNCTION PROTOTYPES
* DEFINED IN PRODUCT'S net_bsp.c
*****************************************************************************************
*/
void NetNIC_LinkUp (void); /* Message from NIC that the ethernet link is up. */
/* Called in interruption context most of the time. */
void NetNIC_LinkDown (void); /* Message from NIC that the ethernet link is down. */
/* Called in interruption context most of the time. */
void DM9161AE_DlyAutoNegAck (void); /* Implement 1.5 s dly. */
/* MUST use OS dly to preempt. */
/*
*****************************************************************************************
* FUNCTION PROTOTYPES
* DEFINED IN PRODUCT'S net_isr.c
*****************************************************************************************
*/
#if (NET_NIC_CFG_INT_CTRL_EN == DEF_ENABLED)
#if (EMAC_CFG_PHY_INT == DEF_ON)
void NetNIC_PhyIntInit (void); /* Init int ctrl'r. */
void NetNIC_PhyIntClr (void); /* Clr int ctrl'r src(s). */
void NetNIC_PhyIntEnter (void); /* Enter ISR [see Note #2]. */
#endif
#endif
/*
*****************************************************************************************
* CONFIGURATION ERRORS
*****************************************************************************************
*/
#ifndef NET_NIC_CFG_INT_CTRL_EN
#error "NET_NIC_CFG_INT_CTRL_EN not #define'd in 'net_cfg.h'"
#error " [MUST be DEF_DISABLED] "
#error " [ || DEF_ENABLED ] "
#elif ((NET_NIC_CFG_INT_CTRL_EN != DEF_DISABLED) && \
(NET_NIC_CFG_INT_CTRL_EN != DEF_ENABLED ))
#error "NET_NIC_CFG_INT_CTRL_EN illegally #define'd in 'net_cfg.h'"
#error " [MUST be DEF_DISABLED] "
#error " [ || DEF_ENABLED ] "
#endif
#ifndef EMAC_CFG_PHY_ADDR
#error "EMAC_CFG_PHY_ADDR not #define'd in 'net_bsp.h'"
#endif
#ifndef EMAC_CFG_RMII
#error "EMAC_CFG_RMII not #define'd in 'net_bsp.h'"
#error " [MUST be DEF_YES ]"
#error " [ || DEF_NO ]"
#elif ((EMAC_CFG_RMII != DEF_YES) && \
(EMAC_CFG_RMII != DEF_NO ))
#error "EMAC_CFG_RMII illegally #define'd in 'net_bsp.h'"
#error " [MUST be DEF_YES]"
#error " [ || DEF_NO ]"
#endif
#endif
/*
*********************************************************************************************************
*
* NETWORK PHYSICAL LAYER
*
* DM9161AE
*
* Filename : phy.c
* Version : V1.0
*********************************************************************************************************
* Note(s) : (1) Supports DM9161AE '3.3V Dual-Speed Fast Ethernet Transceiver' as described in
*
*
* (a) DM9161AE
*
* (2) The MII interface port is assumed to be part of the host EMAC; consequently,
* reads from and writes to the PHY are made through the EMAC. The functions
* NetNIC_PhyRegRd() and NetNIC_PhyRegWr(), which are used to access the PHY, should
* be provided in the EMAC driver.
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
/*#include */
#include
#include
/*
*********************************************************************************************************
*********************************************************************************************************
* GLOBAL FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* NetNIC_PhyInit()
*
* Description : Initialize phyter (ethernet link controller)
* This instance configures the Davicom DM9161AE PHY
*
* Argument(s) : none.
*
* Return(s) : 1 for OK, 0 for error
*
* Caller(s) : EMAC_Init()
*
* Note(s) : Assumes the MDI port as already been enabled for the PHY.
*********************************************************************************************************
*/
void NetNIC_PhyInit (NET_ERR *perr)
{
volatile CPU_INT16U reg_val;
#if (!defined(EMAC_CFG_RMII)) || (EMAC_CFG_RMII <= 0)
reg_val = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMCR, perr); /* Read the Basic Mode Control Register (twice) */
reg_val = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMCR, perr); /* Read the Basic Mode Control Register (twice) */
if (*perr != NET_PHY_ERR_NONE) {
return;
}
reg_val &= ~BMCR_ISOLATE; /* Mask off 'Disconnect from MII bit (BMCR_ISOLATE) */
NetNIC_PhyRegWr(EMAC_CFG_PHY_ADDR, MII_BMCR, reg_val, perr); /* Put the PHY into MII mode */
if (*perr != NET_PHY_ERR_NONE) {
return;
}
#endif
NetNIC_PhyAutoNeg(); /* Perform auto-negotiation */
NetNIC_ConnStatus = NetNIC_PhyLinkState(); /* Set NetNIC_ConnStatus according to link state */
if (NetNIC_ConnStatus == DEF_ON) {
NetNIC_LinkUp();
} else {
NetNIC_LinkDown();
}
#if (EMAC_CFG_PHY_INT == DEF_ON)
NetNIC_PhyIntInit();
reg_val = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, DM9161_MDINTR, perr); /* Clear interrupts */
reg_val |= MDINTER_FDX_MSK | MDINTER_SPD_MSK | MDINTER_LINK_MSK | MDINTER_INTR_MSK;
reg_val &= ~(MDINTER_SPD_MSK | MDINTER_LINK_MSK | MDINTER_INTR_MSK);
NetNIC_PhyRegWr(EMAC_CFG_PHY_ADDR, DM9161_MDINTR, reg_val, perr); /* Enable link change interrupt */
#endif
}
/*
*********************************************************************************************************
* NetNIC_PhyAutoNeg()
*
* Description : Do link auto-negotiation
*
* Argument(s) : None.
*
* Return(s) : None.
*
* Caller(s) : NetNIC_PhyInit().
*
* Note(s) : none.
*********************************************************************************************************
*/
void NetNIC_PhyAutoNeg (void)
{
CPU_INT16U i;
CPU_INT16U reg_val;
CPU_BOOLEAN link;
NET_ERR err;
i = DM9161AE_INIT_AUTO_NEG_RETRIES; /* Set the # of retries before declaring a timeout */
link = NetNIC_PhyLinkState(); /* Get the current link state. 1=linked, 0=no link */
if (link == DEF_OFF) {
#if (!defined(EMAC_CFG_RMII)) || (EMAC_CFG_RMII <= 0)
reg_val = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMCR, &err); /* Get current control register value */
reg_val |= DEF_BIT_09; /* Set the auto-negotiation start bit */
NetNIC_PhyRegWr(AT91C_PHY_ADDR, MII_BMCR, reg_val, &err); /* Initiate auto-negotiation */
#endif
do { /* Do while auto-neg incomplete, or retries expired */
DM9161AE_DlyAutoNegAck(); /* Wait for a while auto-neg to proceed (net_bsp.c) */
reg_val = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err); /* Read the Basic Mode Status Register */
reg_val = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err); /* Read the Basic Mode Status Register */
i--;
} while (((reg_val & BMSR_LSTATUS) == 0) && (i > 0)); /* While link not established and retries remain */
}
}
/*
*********************************************************************************************************
* NetNIC_PhyAutoNegState()
*
* Description : Returns state of auto-negotiation
* This instance probe the Davicom DM9161AE '3.3V Dual-Speed Fast Ethernet Transceiver'
*
* Argument(s) : none.
*
* Return(s) : State of auto-negociation (DEF_OFF = not completed, DEF_ON = completed).
*
* Caller(s) : NetNIC_PhyInit().
*
* Note(s) : If any error is encountered while reading the PHY, this function
* will return Auto Negotiation State = DEF_OFF (incomplete).
*********************************************************************************************************
*/
CPU_BOOLEAN NetNIC_PhyAutoNegState (void)
{
CPU_INT32U reg_val;
NET_ERR err;
reg_val = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err);
reg_val = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err);
if (err != NET_PHY_ERR_NONE) {
reg_val = 0;
}
if ((reg_val & BMSR_ANEGCOMPLETE) == BMSR_ANEGCOMPLETE) { /* DM9161AE register 0x01: Basic Status Register #1 */
return (DEF_ON); /* BIT 5 Signal the result of the auto negotiation */
} else { /* 1 = complete, 0 = incomplete */
return (DEF_OFF);
}
}
/*
*********************************************************************************************************
* NetNIC_PhyLinkState()
*
* Description : Returns state of ethernet link
* This instance probe the Davicom DM9161AE '3.3V Dual-Speed Fast Ethernet Transceiver'
*
* Argument(s) : none.
*
* Return(s) : State of ethernet link (DEF_OFF = link down, DEF_ON = link up).
*
* Caller(s) : NetNIC_PhyISR_Handler().
*
* Note(s) : If any error is encountered while reading the PHY, this function
* will return link state = DEF_OFF.
*********************************************************************************************************
*/
CPU_BOOLEAN NetNIC_PhyLinkState (void)
{
NET_ERR err;
CPU_INT16U reg_val;
/* DM9161AE register 0x01: Basic Status Register #1 */
/* BIT 2 , Link Status, 1 = linked, 0 = not linked. */
reg_val = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err);
reg_val = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err);
if (err != NET_PHY_ERR_NONE) {
reg_val = 0;
}
reg_val &= BMSR_LSTATUS;
if (reg_val == BMSR_LSTATUS) {
return (DEF_ON);
} else {
return (DEF_OFF);
}
}
/*
*********************************************************************************************************
* NetPHY_GetLinkSpeed()
*
* Description : Returns the speed of the current Ethernet link
* This probes the Davicom DM9161AE '3.3V Dual-Speed Fast Ethernet Transceiver'
*
* Argument(s) : none.
*
* Return(s) : 0 = No Link, 10 = 10mbps, 100 = 100mbps
*
* Caller(s) : EMAC_Init()
*
* Note(s) : none.
*********************************************************************************************************
*/
CPU_INT32U NetNIC_PhyLinkSpeed (void)
{
CPU_INT32U bmsr;
CPU_INT32U bmcr;
CPU_INT32U lpa;
NET_ERR err;
bmsr = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err); /* Get Link Status from PHY status reg. Requires 2 reads */
bmsr = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err); /* Get Link Status from PHY status reg. Requires 2 reads */
if ((bmsr & BMSR_LSTATUS) == 0) {
return (NET_PHY_SPD_0); /* No link */
}
bmcr = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMCR, &err); /* Read the PHY Control Register */
if ((bmcr & BMCR_ANENABLE) == BMCR_ANENABLE) { /* If AutoNegotiation is enabled */
if ((bmsr & BMSR_ANEGCOMPLETE) == 0) { /* If AutoNegotiation is not complete */
return (NET_PHY_SPD_0); /* AutoNegotitation in progress */
}
lpa = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_ANLPAR, &err); /* Read the Link Partner Ability Register */
if (((lpa & ANLPAR_100FULL) == ANLPAR_100FULL) || ((lpa & ANLPAR_100HALF) == ANLPAR_100HALF)) {
return (NET_PHY_SPD_100);
} else {
return (NET_PHY_SPD_10);
}
} else { /* Auto-negotiation not enabled, get speed from BMCR */
if ((bmcr & BMCR_SPEED100) == BMCR_SPEED100) {
return (NET_PHY_SPD_100);
} else {
return (NET_PHY_SPD_10);
}
}
}
/*
*********************************************************************************************************
* NetPHY_GetDuplex()
*
* Description : Returns the duplex mode of the current Ethernet link
* This probes the Davicom DM9161AE '3.3V Dual-Speed Fast Ethernet Transceiver'
*
* Argument(s) : none.
*
* Return(s) : 0 = Unknown (Auto-Neg in progress), 1 = Half Duplex, 2 = Full Duplex
*
* Caller(s) : EMAC_Init()
*
* Note(s) : none.
*********************************************************************************************************
*/
CPU_INT32U NetNIC_PhyLinkDuplex (void)
{
CPU_INT32U bmcr;
CPU_INT32U bmsr;
CPU_INT32U lpa;
NET_ERR err;
bmsr = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err); /* Get Link Status from PHY status reg. Requires 2 reads */
bmsr = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMSR, &err); /* Get Link Status from PHY status reg. Requires 2 reads */
if ((bmsr & BMSR_LSTATUS) == 0) {
return (NET_PHY_DUPLEX_UNKNOWN); /* No link, return 'Duplex Uknown' */
}
bmcr = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_BMCR, &err); /* Read the PHY Control Register */
if ((bmcr & BMCR_ANENABLE) == BMCR_ANENABLE) { /* If AutoNegotiation is enabled */
if ((bmsr & BMSR_ANEGCOMPLETE) == 0) { /* If AutoNegotiation is not complete */
return (NET_PHY_DUPLEX_UNKNOWN); /* AutoNegotitation in progress */
}
lpa = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, MII_ANLPAR, &err); /* Read the Link Partner Ability Register */
if (((lpa & ANLPAR_100FULL) == ANLPAR_100FULL) || ((lpa & ANLPAR_10FULL) == ANLPAR_10FULL)) {
return (NET_PHY_DUPLEX_FULL);
} else {
return (NET_PHY_DUPLEX_HALF);
}
} else { /* Auto-negotiation not enabled, get duplex from BMCR */
if ((bmcr & BMCR_FULLDPLX) == BMCR_FULLDPLX) {
return (NET_PHY_DUPLEX_FULL);
} else {
return (NET_PHY_DUPLEX_HALF);
}
}
}
/*
*********************************************************************************************************
*********************************************************************************************************
* GLOBAL FUNCTIONS: PHY INTERRUPTS
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* NetNIC_ISR_Handler()
*
* Description : (1) Update NetNIC_ConnStatus according to link state
*
* Argument(s) : none.
*
* Return(s) : none.
*********************************************************************************************************
*/
#if (EMAC_CFG_PHY_INT == DEF_ON)
void NetNIC_PhyISR_Handler (void)
{
volatile CPU_INT16U reg_val;
NET_ERR err;
NetNIC_PhyIntEnter();
NetNIC_ConnStatus = NetNIC_PhyLinkState(); /* Set NetNIC_ConnStatus according to link state */
if (NetNIC_ConnStatus == DEF_ON) {
NetNIC_LinkUp();
} else {
NetNIC_LinkDown();
}
reg_val = NetNIC_PhyRegRd(EMAC_CFG_PHY_ADDR, DM9161_MDINTR, &err); /* Clear interrupts */
NetNIC_PhyIntClr();
}
#endif