blob: ee9707950a87f6028a1e162779227ab9422b58c1 [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
Bhupesh Sharmac624d162013-07-18 13:58:20 +053032/* RealTek RTL8211x */
33static int rtl8211x_config(struct phy_device *phydev)
Andy Fleming9082eea2011-04-07 21:56:05 -050034{
35 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
36
Codrin Ciubotariu3cee1382015-02-13 14:47:58 +020037 /* mask interrupt at init; if the interrupt is
38 * needed indeed, it should be explicitly enabled
39 */
40 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER,
41 MIIM_RTL8211x_PHY_INTR_DIS);
42
43 /* read interrupt status just to clear it */
44 phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER);
45
Andy Fleming9082eea2011-04-07 21:56:05 -050046 genphy_config_aneg(phydev);
47
48 return 0;
49}
50
Bhupesh Sharmac624d162013-07-18 13:58:20 +053051static int rtl8211x_parse_status(struct phy_device *phydev)
Andy Fleming9082eea2011-04-07 21:56:05 -050052{
53 unsigned int speed;
54 unsigned int mii_reg;
55
Bhupesh Sharmac624d162013-07-18 13:58:20 +053056 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_STATUS);
Andy Fleming9082eea2011-04-07 21:56:05 -050057
Bhupesh Sharmac624d162013-07-18 13:58:20 +053058 if (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) {
Andy Fleming9082eea2011-04-07 21:56:05 -050059 int i = 0;
60
61 /* in case of timeout ->link is cleared */
62 phydev->link = 1;
63 puts("Waiting for PHY realtime link");
Bhupesh Sharmac624d162013-07-18 13:58:20 +053064 while (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) {
Andy Fleming9082eea2011-04-07 21:56:05 -050065 /* Timeout reached ? */
66 if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
67 puts(" TIMEOUT !\n");
68 phydev->link = 0;
69 break;
70 }
71
72 if ((i++ % 1000) == 0)
73 putc('.');
74 udelay(1000); /* 1 ms */
75 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE,
Bhupesh Sharmac624d162013-07-18 13:58:20 +053076 MIIM_RTL8211x_PHY_STATUS);
Andy Fleming9082eea2011-04-07 21:56:05 -050077 }
78 puts(" done\n");
79 udelay(500000); /* another 500 ms (results in faster booting) */
80 } else {
Bhupesh Sharmac624d162013-07-18 13:58:20 +053081 if (mii_reg & MIIM_RTL8211x_PHYSTAT_LINK)
Andy Fleming9082eea2011-04-07 21:56:05 -050082 phydev->link = 1;
83 else
84 phydev->link = 0;
85 }
86
Bhupesh Sharmac624d162013-07-18 13:58:20 +053087 if (mii_reg & MIIM_RTL8211x_PHYSTAT_DUPLEX)
Andy Fleming9082eea2011-04-07 21:56:05 -050088 phydev->duplex = DUPLEX_FULL;
89 else
90 phydev->duplex = DUPLEX_HALF;
91
Bhupesh Sharmac624d162013-07-18 13:58:20 +053092 speed = (mii_reg & MIIM_RTL8211x_PHYSTAT_SPEED);
Andy Fleming9082eea2011-04-07 21:56:05 -050093
94 switch (speed) {
Bhupesh Sharmac624d162013-07-18 13:58:20 +053095 case MIIM_RTL8211x_PHYSTAT_GBIT:
Andy Fleming9082eea2011-04-07 21:56:05 -050096 phydev->speed = SPEED_1000;
97 break;
Bhupesh Sharmac624d162013-07-18 13:58:20 +053098 case MIIM_RTL8211x_PHYSTAT_100:
Andy Fleming9082eea2011-04-07 21:56:05 -050099 phydev->speed = SPEED_100;
100 break;
101 default:
102 phydev->speed = SPEED_10;
103 }
104
105 return 0;
106}
107
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530108static int rtl8211x_startup(struct phy_device *phydev)
Andy Fleming9082eea2011-04-07 21:56:05 -0500109{
110 /* Read the Status (2x to make sure link is right) */
111 genphy_update_link(phydev);
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530112 rtl8211x_parse_status(phydev);
Andy Fleming9082eea2011-04-07 21:56:05 -0500113
114 return 0;
115}
116
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530117/* Support for RTL8211B PHY */
Andy Fleming9082eea2011-04-07 21:56:05 -0500118static struct phy_driver RTL8211B_driver = {
119 .name = "RealTek RTL8211B",
120 .uid = 0x1cc910,
Bhupesh Sharma42205042013-09-01 04:40:52 +0530121 .mask = 0xffffff,
Andy Fleming9082eea2011-04-07 21:56:05 -0500122 .features = PHY_GBIT_FEATURES,
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530123 .config = &rtl8211x_config,
124 .startup = &rtl8211x_startup,
125 .shutdown = &genphy_shutdown,
126};
127
128/* Support for RTL8211E-VB-CG, RTL8211E-VL-CG and RTL8211EG-VB-CG PHYs */
129static struct phy_driver RTL8211E_driver = {
130 .name = "RealTek RTL8211E",
131 .uid = 0x1cc915,
Bhupesh Sharma42205042013-09-01 04:40:52 +0530132 .mask = 0xffffff,
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530133 .features = PHY_GBIT_FEATURES,
134 .config = &rtl8211x_config,
135 .startup = &rtl8211x_startup,
136 .shutdown = &genphy_shutdown,
137};
138
139/* Support for RTL8211DN PHY */
140static struct phy_driver RTL8211DN_driver = {
141 .name = "RealTek RTL8211DN",
142 .uid = 0x1cc914,
Bhupesh Sharma42205042013-09-01 04:40:52 +0530143 .mask = 0xffffff,
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530144 .features = PHY_GBIT_FEATURES,
145 .config = &rtl8211x_config,
146 .startup = &rtl8211x_startup,
Andy Fleming9082eea2011-04-07 21:56:05 -0500147 .shutdown = &genphy_shutdown,
148};
149
150int phy_realtek_init(void)
151{
152 phy_register(&RTL8211B_driver);
Bhupesh Sharmac624d162013-07-18 13:58:20 +0530153 phy_register(&RTL8211E_driver);
154 phy_register(&RTL8211DN_driver);
Andy Fleming9082eea2011-04-07 21:56:05 -0500155
156 return 0;
157}