net: phy: Optionally force master mode for RTL PHY
[oweals/u-boot.git] / drivers / net / phy / realtek.c
1 /*
2  * RealTek PHY drivers
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  *
6  * Copyright 2010-2011, 2015 Freescale Semiconductor, Inc.
7  * author Andy Fleming
8  */
9 #include <config.h>
10 #include <common.h>
11 #include <phy.h>
12
13 #define PHY_AUTONEGOTIATE_TIMEOUT 5000
14
15 /* RTL8211x 1000BASE-T Control Register */
16 #define MIIM_RTL8211x_CTRL1000T_MSCE (1 << 12);
17 #define MIIM_RTL8211X_CTRL1000T_MASTER (1 << 11);
18
19 /* RTL8211x PHY Status Register */
20 #define MIIM_RTL8211x_PHY_STATUS       0x11
21 #define MIIM_RTL8211x_PHYSTAT_SPEED    0xc000
22 #define MIIM_RTL8211x_PHYSTAT_GBIT     0x8000
23 #define MIIM_RTL8211x_PHYSTAT_100      0x4000
24 #define MIIM_RTL8211x_PHYSTAT_DUPLEX   0x2000
25 #define MIIM_RTL8211x_PHYSTAT_SPDDONE  0x0800
26 #define MIIM_RTL8211x_PHYSTAT_LINK     0x0400
27
28 /* RTL8211x PHY Interrupt Enable Register */
29 #define MIIM_RTL8211x_PHY_INER         0x12
30 #define MIIM_RTL8211x_PHY_INTR_ENA     0x9f01
31 #define MIIM_RTL8211x_PHY_INTR_DIS     0x0000
32
33 /* RTL8211x PHY Interrupt Status Register */
34 #define MIIM_RTL8211x_PHY_INSR         0x13
35
36 /* RTL8211F PHY Status Register */
37 #define MIIM_RTL8211F_PHY_STATUS       0x1a
38 #define MIIM_RTL8211F_AUTONEG_ENABLE   0x1000
39 #define MIIM_RTL8211F_PHYSTAT_SPEED    0x0030
40 #define MIIM_RTL8211F_PHYSTAT_GBIT     0x0020
41 #define MIIM_RTL8211F_PHYSTAT_100      0x0010
42 #define MIIM_RTL8211F_PHYSTAT_DUPLEX   0x0008
43 #define MIIM_RTL8211F_PHYSTAT_SPDDONE  0x0800
44 #define MIIM_RTL8211F_PHYSTAT_LINK     0x0004
45
46 #define MIIM_RTL8211F_PAGE_SELECT      0x1f
47 #define MIIM_RTL8211F_TX_DELAY          0x100
48 #define MIIM_RTL8211F_LCR               0x10
49
50 /* RealTek RTL8211x */
51 static int rtl8211x_config(struct phy_device *phydev)
52 {
53         phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
54
55         /* mask interrupt at init; if the interrupt is
56          * needed indeed, it should be explicitly enabled
57          */
58         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER,
59                   MIIM_RTL8211x_PHY_INTR_DIS);
60 #ifdef CONFIG_RTL8211X_PHY_FORCE_MASTER
61         unsigned int reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000);
62         /* force manual master/slave configuration */
63         reg |= MIIM_RTL8211x_CTRL1000T_MSCE;
64         /* force master mode */
65         reg |= MIIM_RTL8211X_CTRL1000T_MASTER;
66         phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, reg);
67 #endif
68         /* read interrupt status just to clear it */
69         phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER);
70
71         genphy_config_aneg(phydev);
72
73         return 0;
74 }
75
76 static int rtl8211f_config(struct phy_device *phydev)
77 {
78         u16 reg;
79
80         phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
81
82         if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
83                 /* enable TXDLY */
84                 phy_write(phydev, MDIO_DEVAD_NONE,
85                           MIIM_RTL8211F_PAGE_SELECT, 0xd08);
86                 reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x11);
87                 reg |= MIIM_RTL8211F_TX_DELAY;
88                 phy_write(phydev, MDIO_DEVAD_NONE, 0x11, reg);
89                 /* restore to default page 0 */
90                 phy_write(phydev, MDIO_DEVAD_NONE,
91                           MIIM_RTL8211F_PAGE_SELECT, 0x0);
92         }
93
94         /* Set green LED for Link, yellow LED for Active */
95         phy_write(phydev, MDIO_DEVAD_NONE,
96                   MIIM_RTL8211F_PAGE_SELECT, 0xd04);
97         phy_write(phydev, MDIO_DEVAD_NONE, 0x10, 0x617f);
98         phy_write(phydev, MDIO_DEVAD_NONE,
99                   MIIM_RTL8211F_PAGE_SELECT, 0x0);
100
101         genphy_config_aneg(phydev);
102
103         return 0;
104 }
105
106 static int rtl8211x_parse_status(struct phy_device *phydev)
107 {
108         unsigned int speed;
109         unsigned int mii_reg;
110
111         mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_STATUS);
112
113         if (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) {
114                 int i = 0;
115
116                 /* in case of timeout ->link is cleared */
117                 phydev->link = 1;
118                 puts("Waiting for PHY realtime link");
119                 while (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) {
120                         /* Timeout reached ? */
121                         if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
122                                 puts(" TIMEOUT !\n");
123                                 phydev->link = 0;
124                                 break;
125                         }
126
127                         if ((i++ % 1000) == 0)
128                                 putc('.');
129                         udelay(1000);   /* 1 ms */
130                         mii_reg = phy_read(phydev, MDIO_DEVAD_NONE,
131                                         MIIM_RTL8211x_PHY_STATUS);
132                 }
133                 puts(" done\n");
134                 udelay(500000); /* another 500 ms (results in faster booting) */
135         } else {
136                 if (mii_reg & MIIM_RTL8211x_PHYSTAT_LINK)
137                         phydev->link = 1;
138                 else
139                         phydev->link = 0;
140         }
141
142         if (mii_reg & MIIM_RTL8211x_PHYSTAT_DUPLEX)
143                 phydev->duplex = DUPLEX_FULL;
144         else
145                 phydev->duplex = DUPLEX_HALF;
146
147         speed = (mii_reg & MIIM_RTL8211x_PHYSTAT_SPEED);
148
149         switch (speed) {
150         case MIIM_RTL8211x_PHYSTAT_GBIT:
151                 phydev->speed = SPEED_1000;
152                 break;
153         case MIIM_RTL8211x_PHYSTAT_100:
154                 phydev->speed = SPEED_100;
155                 break;
156         default:
157                 phydev->speed = SPEED_10;
158         }
159
160         return 0;
161 }
162
163 static int rtl8211f_parse_status(struct phy_device *phydev)
164 {
165         unsigned int speed;
166         unsigned int mii_reg;
167         int i = 0;
168
169         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, 0xa43);
170         mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PHY_STATUS);
171
172         phydev->link = 1;
173         while (!(mii_reg & MIIM_RTL8211F_PHYSTAT_LINK)) {
174                 if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
175                         puts(" TIMEOUT !\n");
176                         phydev->link = 0;
177                         break;
178                 }
179
180                 if ((i++ % 1000) == 0)
181                         putc('.');
182                 udelay(1000);
183                 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE,
184                                    MIIM_RTL8211F_PHY_STATUS);
185         }
186
187         if (mii_reg & MIIM_RTL8211F_PHYSTAT_DUPLEX)
188                 phydev->duplex = DUPLEX_FULL;
189         else
190                 phydev->duplex = DUPLEX_HALF;
191
192         speed = (mii_reg & MIIM_RTL8211F_PHYSTAT_SPEED);
193
194         switch (speed) {
195         case MIIM_RTL8211F_PHYSTAT_GBIT:
196                 phydev->speed = SPEED_1000;
197                 break;
198         case MIIM_RTL8211F_PHYSTAT_100:
199                 phydev->speed = SPEED_100;
200                 break;
201         default:
202                 phydev->speed = SPEED_10;
203         }
204
205         return 0;
206 }
207
208 static int rtl8211x_startup(struct phy_device *phydev)
209 {
210         /* Read the Status (2x to make sure link is right) */
211         genphy_update_link(phydev);
212         rtl8211x_parse_status(phydev);
213
214         return 0;
215 }
216
217 static int rtl8211e_startup(struct phy_device *phydev)
218 {
219         genphy_update_link(phydev);
220         genphy_parse_link(phydev);
221
222         return 0;
223 }
224
225 static int rtl8211f_startup(struct phy_device *phydev)
226 {
227         /* Read the Status (2x to make sure link is right) */
228         genphy_update_link(phydev);
229         rtl8211f_parse_status(phydev);
230
231         return 0;
232 }
233
234 /* Support for RTL8211B PHY */
235 static struct phy_driver RTL8211B_driver = {
236         .name = "RealTek RTL8211B",
237         .uid = 0x1cc910,
238         .mask = 0xffffff,
239         .features = PHY_GBIT_FEATURES,
240         .config = &rtl8211x_config,
241         .startup = &rtl8211x_startup,
242         .shutdown = &genphy_shutdown,
243 };
244
245 /* Support for RTL8211E-VB-CG, RTL8211E-VL-CG and RTL8211EG-VB-CG PHYs */
246 static struct phy_driver RTL8211E_driver = {
247         .name = "RealTek RTL8211E",
248         .uid = 0x1cc915,
249         .mask = 0xffffff,
250         .features = PHY_GBIT_FEATURES,
251         .config = &rtl8211x_config,
252         .startup = &rtl8211e_startup,
253         .shutdown = &genphy_shutdown,
254 };
255
256 /* Support for RTL8211DN PHY */
257 static struct phy_driver RTL8211DN_driver = {
258         .name = "RealTek RTL8211DN",
259         .uid = 0x1cc914,
260         .mask = 0xffffff,
261         .features = PHY_GBIT_FEATURES,
262         .config = &rtl8211x_config,
263         .startup = &rtl8211x_startup,
264         .shutdown = &genphy_shutdown,
265 };
266
267 /* Support for RTL8211F PHY */
268 static struct phy_driver RTL8211F_driver = {
269         .name = "RealTek RTL8211F",
270         .uid = 0x1cc916,
271         .mask = 0xffffff,
272         .features = PHY_GBIT_FEATURES,
273         .config = &rtl8211f_config,
274         .startup = &rtl8211f_startup,
275         .shutdown = &genphy_shutdown,
276 };
277
278 int phy_realtek_init(void)
279 {
280         phy_register(&RTL8211B_driver);
281         phy_register(&RTL8211E_driver);
282         phy_register(&RTL8211F_driver);
283         phy_register(&RTL8211DN_driver);
284
285         return 0;
286 }