net: phy/realtek: Add support for RTL8211DN and RTL8211E phy modules

This patch adds support for Realtek PHY modules RTL8211DN and
RTL8211E (variants: RTL8211E-VB-CG, RTL8211E-VL-CG, RTL8211EG-VB-CG),
which can be found on Freescale's T1040RDB boards.

To make the driver more generic across 8211 family, a generic name 8211x
is added for macros and function names.

Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com>
Acked-by: York Sun <yorksun@freescale.com>
This commit is contained in:
Bhupesh Sharma 2013-07-18 13:58:20 +05:30 committed by Joe Hershberger
parent 2eb60902a0
commit c624d168bf
1 changed files with 49 additions and 24 deletions

View File

@ -12,18 +12,18 @@
#define PHY_AUTONEGOTIATE_TIMEOUT 5000 #define PHY_AUTONEGOTIATE_TIMEOUT 5000
/* RTL8211B PHY Status Register */ /* RTL8211x PHY Status Register */
#define MIIM_RTL8211B_PHY_STATUS 0x11 #define MIIM_RTL8211x_PHY_STATUS 0x11
#define MIIM_RTL8211B_PHYSTAT_SPEED 0xc000 #define MIIM_RTL8211x_PHYSTAT_SPEED 0xc000
#define MIIM_RTL8211B_PHYSTAT_GBIT 0x8000 #define MIIM_RTL8211x_PHYSTAT_GBIT 0x8000
#define MIIM_RTL8211B_PHYSTAT_100 0x4000 #define MIIM_RTL8211x_PHYSTAT_100 0x4000
#define MIIM_RTL8211B_PHYSTAT_DUPLEX 0x2000 #define MIIM_RTL8211x_PHYSTAT_DUPLEX 0x2000
#define MIIM_RTL8211B_PHYSTAT_SPDDONE 0x0800 #define MIIM_RTL8211x_PHYSTAT_SPDDONE 0x0800
#define MIIM_RTL8211B_PHYSTAT_LINK 0x0400 #define MIIM_RTL8211x_PHYSTAT_LINK 0x0400
/* RealTek RTL8211B */ /* RealTek RTL8211x */
static int rtl8211b_config(struct phy_device *phydev) static int rtl8211x_config(struct phy_device *phydev)
{ {
phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
@ -32,20 +32,20 @@ static int rtl8211b_config(struct phy_device *phydev)
return 0; return 0;
} }
static int rtl8211b_parse_status(struct phy_device *phydev) static int rtl8211x_parse_status(struct phy_device *phydev)
{ {
unsigned int speed; unsigned int speed;
unsigned int mii_reg; unsigned int mii_reg;
mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211B_PHY_STATUS); mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_STATUS);
if (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) { if (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) {
int i = 0; int i = 0;
/* in case of timeout ->link is cleared */ /* in case of timeout ->link is cleared */
phydev->link = 1; phydev->link = 1;
puts("Waiting for PHY realtime link"); puts("Waiting for PHY realtime link");
while (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) { while (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) {
/* Timeout reached ? */ /* Timeout reached ? */
if (i > PHY_AUTONEGOTIATE_TIMEOUT) { if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
puts(" TIMEOUT !\n"); puts(" TIMEOUT !\n");
@ -57,29 +57,29 @@ static int rtl8211b_parse_status(struct phy_device *phydev)
putc('.'); putc('.');
udelay(1000); /* 1 ms */ udelay(1000); /* 1 ms */
mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, mii_reg = phy_read(phydev, MDIO_DEVAD_NONE,
MIIM_RTL8211B_PHY_STATUS); MIIM_RTL8211x_PHY_STATUS);
} }
puts(" done\n"); puts(" done\n");
udelay(500000); /* another 500 ms (results in faster booting) */ udelay(500000); /* another 500 ms (results in faster booting) */
} else { } else {
if (mii_reg & MIIM_RTL8211B_PHYSTAT_LINK) if (mii_reg & MIIM_RTL8211x_PHYSTAT_LINK)
phydev->link = 1; phydev->link = 1;
else else
phydev->link = 0; phydev->link = 0;
} }
if (mii_reg & MIIM_RTL8211B_PHYSTAT_DUPLEX) if (mii_reg & MIIM_RTL8211x_PHYSTAT_DUPLEX)
phydev->duplex = DUPLEX_FULL; phydev->duplex = DUPLEX_FULL;
else else
phydev->duplex = DUPLEX_HALF; phydev->duplex = DUPLEX_HALF;
speed = (mii_reg & MIIM_RTL8211B_PHYSTAT_SPEED); speed = (mii_reg & MIIM_RTL8211x_PHYSTAT_SPEED);
switch (speed) { switch (speed) {
case MIIM_RTL8211B_PHYSTAT_GBIT: case MIIM_RTL8211x_PHYSTAT_GBIT:
phydev->speed = SPEED_1000; phydev->speed = SPEED_1000;
break; break;
case MIIM_RTL8211B_PHYSTAT_100: case MIIM_RTL8211x_PHYSTAT_100:
phydev->speed = SPEED_100; phydev->speed = SPEED_100;
break; break;
default: default:
@ -89,28 +89,53 @@ static int rtl8211b_parse_status(struct phy_device *phydev)
return 0; return 0;
} }
static int rtl8211b_startup(struct phy_device *phydev) static int rtl8211x_startup(struct phy_device *phydev)
{ {
/* Read the Status (2x to make sure link is right) */ /* Read the Status (2x to make sure link is right) */
genphy_update_link(phydev); genphy_update_link(phydev);
rtl8211b_parse_status(phydev); rtl8211x_parse_status(phydev);
return 0; return 0;
} }
/* Support for RTL8211B PHY */
static struct phy_driver RTL8211B_driver = { static struct phy_driver RTL8211B_driver = {
.name = "RealTek RTL8211B", .name = "RealTek RTL8211B",
.uid = 0x1cc910, .uid = 0x1cc910,
.mask = 0xfffff0, .mask = 0xfffff0,
.features = PHY_GBIT_FEATURES, .features = PHY_GBIT_FEATURES,
.config = &rtl8211b_config, .config = &rtl8211x_config,
.startup = &rtl8211b_startup, .startup = &rtl8211x_startup,
.shutdown = &genphy_shutdown,
};
/* Support for RTL8211E-VB-CG, RTL8211E-VL-CG and RTL8211EG-VB-CG PHYs */
static struct phy_driver RTL8211E_driver = {
.name = "RealTek RTL8211E",
.uid = 0x1cc915,
.mask = 0xfffff0,
.features = PHY_GBIT_FEATURES,
.config = &rtl8211x_config,
.startup = &rtl8211x_startup,
.shutdown = &genphy_shutdown,
};
/* Support for RTL8211DN PHY */
static struct phy_driver RTL8211DN_driver = {
.name = "RealTek RTL8211DN",
.uid = 0x1cc914,
.mask = 0xfffff0,
.features = PHY_GBIT_FEATURES,
.config = &rtl8211x_config,
.startup = &rtl8211x_startup,
.shutdown = &genphy_shutdown, .shutdown = &genphy_shutdown,
}; };
int phy_realtek_init(void) int phy_realtek_init(void)
{ {
phy_register(&RTL8211B_driver); phy_register(&RTL8211B_driver);
phy_register(&RTL8211E_driver);
phy_register(&RTL8211DN_driver);
return 0; return 0;
} }