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