blob: 259a87fcc59ed4bd29c7c96cfc88e865ab975473 [file] [log] [blame]
Andy Fleming9082eea2011-04-07 21:56:05 -05001/*
2 * RealTek PHY drivers
3 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02004 * SPDX-License-Identifier: GPL-2.0+
Andy Fleming9082eea2011-04-07 21:56:05 -05005 *
Codrin Ciubotariu3cee1382015-02-13 14:47:58 +02006 * Copyright 2010-2011, 2015 Freescale Semiconductor, Inc.
Andy Fleming9082eea2011-04-07 21:56:05 -05007 * author Andy Fleming
Andy Fleming9082eea2011-04-07 21:56:05 -05008 */
9#include <config.h>
10#include <common.h>
11#include <phy.h>
12
13#define PHY_AUTONEGOTIATE_TIMEOUT 5000
14
Bhupesh Sharmac624d162013-07-18 13:58:20 +053015/* 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
Andy Fleming9082eea2011-04-07 21:56:05 -050023
Codrin Ciubotariu3cee1382015-02-13 14:47:58 +020024/* 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
Andy Fleming9082eea2011-04-07 21:56:05 -050031
Shengzhou Liu3d6af742015-03-12 18:54:59 +080032/* 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
Shengzhou Liu793ea942015-04-24 16:57:17 +080043#define MIIM_RTL8211F_TX_DELAY 0x100
Shengzhou Liu90712742015-05-21 18:07:35 +080044#define MIIM_RTL8211F_LCR 0x10
Shengzhou Liu3d6af742015-03-12 18:54:59 +080045
Bhupesh Sharmac624d162013-07-18 13:58:20 +053046/* RealTek RTL8211x */
47static int rtl8211x_config(struct phy_device *phydev)
Andy Fleming9082eea2011-04-07 21:56:05 -050048{
49 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
50
Codrin Ciubotariu3cee1382015-02-13 14:47:58 +020051 /* 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
Andy Fleming9082eea2011-04-07 21:56:05 -050060 genphy_config_aneg(phydev);
61
62 return 0;
63}
64
Shengzhou Liu793ea942015-04-24 16:57:17 +080065static 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
Shengzhou Liu90712742015-05-21 18:07:35 +080083 /* 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
Shengzhou Liu793ea942015-04-24 16:57:17 +080090 genphy_config_aneg(phydev);
91
92 return 0;
93}
94
Bhupesh Sharmac624d162013-07-18 13:58:20 +053095static int rtl8211x_parse_status(struct phy_device *phydev)
Andy Fleming9082eea2011-04-07 21:56:05 -050096{
97 unsigned int speed;
98 unsigned int mii_reg;
99
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530100 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_STATUS);
Andy Fleming9082eea2011-04-07 21:56:05 -0500101
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530102 if (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) {
Andy Fleming9082eea2011-04-07 21:56:05 -0500103 int i = 0;
104
105 /* in case of timeout ->link is cleared */
106 phydev->link = 1;
107 puts("Waiting for PHY realtime link");
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530108 while (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) {
Andy Fleming9082eea2011-04-07 21:56:05 -0500109 /* 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,
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530120 MIIM_RTL8211x_PHY_STATUS);
Andy Fleming9082eea2011-04-07 21:56:05 -0500121 }
122 puts(" done\n");
123 udelay(500000); /* another 500 ms (results in faster booting) */
124 } else {
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530125 if (mii_reg & MIIM_RTL8211x_PHYSTAT_LINK)
Andy Fleming9082eea2011-04-07 21:56:05 -0500126 phydev->link = 1;
127 else
128 phydev->link = 0;
129 }
130
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530131 if (mii_reg & MIIM_RTL8211x_PHYSTAT_DUPLEX)
Andy Fleming9082eea2011-04-07 21:56:05 -0500132 phydev->duplex = DUPLEX_FULL;
133 else
134 phydev->duplex = DUPLEX_HALF;
135
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530136 speed = (mii_reg & MIIM_RTL8211x_PHYSTAT_SPEED);
Andy Fleming9082eea2011-04-07 21:56:05 -0500137
138 switch (speed) {
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530139 case MIIM_RTL8211x_PHYSTAT_GBIT:
Andy Fleming9082eea2011-04-07 21:56:05 -0500140 phydev->speed = SPEED_1000;
141 break;
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530142 case MIIM_RTL8211x_PHYSTAT_100:
Andy Fleming9082eea2011-04-07 21:56:05 -0500143 phydev->speed = SPEED_100;
144 break;
145 default:
146 phydev->speed = SPEED_10;
147 }
148
149 return 0;
150}
151
Shengzhou Liu3d6af742015-03-12 18:54:59 +0800152static 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
Shengzhou Liu3d6af742015-03-12 18:54:59 +0800194 return 0;
195}
196
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530197static int rtl8211x_startup(struct phy_device *phydev)
Andy Fleming9082eea2011-04-07 21:56:05 -0500198{
199 /* Read the Status (2x to make sure link is right) */
200 genphy_update_link(phydev);
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530201 rtl8211x_parse_status(phydev);
Andy Fleming9082eea2011-04-07 21:56:05 -0500202
203 return 0;
204}
205
Michal Simek6a10bc52016-02-13 10:31:32 +0100206static int rtl8211e_startup(struct phy_device *phydev)
207{
208 genphy_update_link(phydev);
209 genphy_parse_link(phydev);
210
211 return 0;
212}
213
Shengzhou Liu3d6af742015-03-12 18:54:59 +0800214static int rtl8211f_startup(struct phy_device *phydev)
215{
216 /* Read the Status (2x to make sure link is right) */
217 genphy_update_link(phydev);
218 rtl8211f_parse_status(phydev);
219
220 return 0;
221}
222
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530223/* Support for RTL8211B PHY */
Andy Fleming9082eea2011-04-07 21:56:05 -0500224static struct phy_driver RTL8211B_driver = {
225 .name = "RealTek RTL8211B",
226 .uid = 0x1cc910,
Bhupesh Sharma42205042013-09-01 04:40:52 +0530227 .mask = 0xffffff,
Andy Fleming9082eea2011-04-07 21:56:05 -0500228 .features = PHY_GBIT_FEATURES,
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530229 .config = &rtl8211x_config,
230 .startup = &rtl8211x_startup,
231 .shutdown = &genphy_shutdown,
232};
233
234/* Support for RTL8211E-VB-CG, RTL8211E-VL-CG and RTL8211EG-VB-CG PHYs */
235static struct phy_driver RTL8211E_driver = {
236 .name = "RealTek RTL8211E",
237 .uid = 0x1cc915,
Bhupesh Sharma42205042013-09-01 04:40:52 +0530238 .mask = 0xffffff,
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530239 .features = PHY_GBIT_FEATURES,
240 .config = &rtl8211x_config,
Michal Simek6a10bc52016-02-13 10:31:32 +0100241 .startup = &rtl8211e_startup,
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530242 .shutdown = &genphy_shutdown,
243};
244
245/* Support for RTL8211DN PHY */
246static struct phy_driver RTL8211DN_driver = {
247 .name = "RealTek RTL8211DN",
248 .uid = 0x1cc914,
Bhupesh Sharma42205042013-09-01 04:40:52 +0530249 .mask = 0xffffff,
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530250 .features = PHY_GBIT_FEATURES,
251 .config = &rtl8211x_config,
252 .startup = &rtl8211x_startup,
Andy Fleming9082eea2011-04-07 21:56:05 -0500253 .shutdown = &genphy_shutdown,
254};
255
Shengzhou Liu3d6af742015-03-12 18:54:59 +0800256/* Support for RTL8211F PHY */
257static struct phy_driver RTL8211F_driver = {
258 .name = "RealTek RTL8211F",
259 .uid = 0x1cc916,
260 .mask = 0xffffff,
261 .features = PHY_GBIT_FEATURES,
Shengzhou Liu793ea942015-04-24 16:57:17 +0800262 .config = &rtl8211f_config,
Shengzhou Liu3d6af742015-03-12 18:54:59 +0800263 .startup = &rtl8211f_startup,
264 .shutdown = &genphy_shutdown,
265};
266
Andy Fleming9082eea2011-04-07 21:56:05 -0500267int phy_realtek_init(void)
268{
269 phy_register(&RTL8211B_driver);
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530270 phy_register(&RTL8211E_driver);
Shengzhou Liu3d6af742015-03-12 18:54:59 +0800271 phy_register(&RTL8211F_driver);
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530272 phy_register(&RTL8211DN_driver);
Andy Fleming9082eea2011-04-07 21:56:05 -0500273
274 return 0;
275}