1 #include <stdio.h>
2 #include "app_phy.h"
3
4 #define PHY_BASE_ADDR 0x7
5
6 #define PHY_REG_CONTROL 0x0
7 #define PHY_REG_STATUS 0x1
8 #define PHY_REG_ANE 0x6
9 #define PHY_REG_SPEC_STATUS 0x11
10 #define PHY_REG_EXTEND_STATUS 0x1B
11
12 #define PHY_BIT_CONTROL_RESET 0x8000 /*!< Control reg : reset */
13 #define PHY_BIT_CONTROL_ANEN 0x1000 /*!< Control reg : auto-negotiation enable */
14 #define PHY_BIT_CONTROL_RSAN 0x0200 /*!< Control reg : auto-negotiation restart */
15
16 #define PHY_BIT_STATUS_ANC 0x0020 /*!< Status reg : auto-negotiation complete */
17 #define PHY_BIT_STATUS_LINK 0x0004 /*!< Status reg : link is up */
18
19 #define PHY_BIT_ANE_LPAN 0x0001 /*!< ANE reg : link partner can auto-neg */
20
21 #define PHY_BIT_SPEED 0xC000 /*!< specific status reg : speed */
22 #define PHY_BIT_DUPLEX 0x2000 /*!< specific status reg : duplex */
23
24 #define PHY_BIT_AUTO_MEDIA_DISABLE 0x8000 /*!< extended status reg : auto media select disable */
25 #define PHY_BIT_AUTO_MEDIA_REG_DISABLE 0x0200 /*!< extended status reg : auto media register select disable */
26
phy_Reset()27 void phy_Reset() {
28 ETH_PhyWrite(PHY_BASE_ADDR, PHY_REG_CONTROL, PHY_BIT_CONTROL_RESET);
29
30 while (1) {
31 uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_CONTROL);
32 if ((ret & PHY_BIT_CONTROL_RESET) == 0) {
33 break;
34 }
35 }
36 }
37
phy_AutoMediaSelect()38 void phy_AutoMediaSelect() {
39 uint32_t data;
40
41 // auto media and auto media register selection
42 data = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_EXTEND_STATUS);
43 data &= ~PHY_BIT_AUTO_MEDIA_DISABLE;
44 data &= ~PHY_BIT_AUTO_MEDIA_REG_DISABLE;
45 ETH_PhyWrite(PHY_BASE_ADDR, PHY_REG_EXTEND_STATUS, data);
46 }
47
phy_AutoNeg()48 void phy_AutoNeg()
49 {
50 uint32_t data;
51
52 data = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_CONTROL);
53 data |= (PHY_BIT_CONTROL_ANEN | PHY_BIT_CONTROL_RSAN);
54 ETH_PhyWrite(PHY_BASE_ADDR, PHY_REG_CONTROL, data);
55
56 while (1)
57 {
58 uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_STATUS);
59 if ((ret & PHY_BIT_STATUS_ANC) == PHY_BIT_STATUS_ANC)
60 {
61 break;
62 }
63 rt_thread_delay(1);
64 }
65 }
66
phy_IsLink()67 BOOL phy_IsLink() {
68 uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_STATUS);
69 return (ret & PHY_BIT_STATUS_LINK) ? TRUE : FALSE;
70 }
71
phy_PartnerCanAutoNeg()72 BOOL phy_PartnerCanAutoNeg() {
73 uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_ANE);
74 return (ret & PHY_BIT_ANE_LPAN) ? TRUE : FALSE;
75 }
76
phy_GetSpeed()77 uint32_t phy_GetSpeed() {
78 uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_SPEC_STATUS);
79 return ((ret & PHY_BIT_SPEED) >> 14);
80 }
81
phy_GetDuplex()82 uint32_t phy_GetDuplex() {
83 uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_SPEC_STATUS);
84 return ((ret & PHY_BIT_DUPLEX) >> 13);
85 }
86
phy_Init()87 BOOL phy_Init() {
88 phy_AutoMediaSelect();
89 phy_AutoNeg();
90
91 if (!phy_PartnerCanAutoNeg()) {
92 printf("Warning:: PHY's partner can't do auto-negotiation\n");
93 }
94
95 if (!phy_IsLink()) {
96 printf("link is down\n");
97 return FALSE;
98 }
99
100 {
101 uint32_t speed = phy_GetSpeed();
102 if (speed == PHY_SPEED_10) {
103 speed = 10;
104 } else if (speed == PHY_SPEED_100) {
105 speed = 100;
106 } else if (speed == PHY_SPEED_1000) {
107 speed = 1000;
108 }
109
110 printf("PHY runs in %uM speed %s duplex\n",
111 speed, (phy_GetDuplex() == PHY_DUPLEX_HALF) ? "half" : "full");
112 }
113
114 // After auto-negcioation, Mawell PHY need some
115 // time to initial itself.
116 // So we have to delay some time since different
117 // connection way, such as direct wire, hub, switch.
118 // If not to delay, the first several sent frame
119 // may be lost.
120 // Please according to actual environment to tune
121 // this delay.
122 udelay(200000);
123
124 return TRUE;
125 }
126