Home | History | Annotate | Download | only in phy
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * RealTek PHY drivers
      4  *
      5  * Copyright 2010-2011, 2015 Freescale Semiconductor, Inc.
      6  * author Andy Fleming
      7  * Copyright 2016 Karsten Merker <merker (at) debian.org>
      8  */
      9 #include <config.h>
     10 #include <common.h>
     11 #include <linux/bitops.h>
     12 #include <phy.h>
     13 
     14 #define PHY_RTL8211x_FORCE_MASTER BIT(1)
     15 #define PHY_RTL8211E_PINE64_GIGABIT_FIX BIT(2)
     16 
     17 #define PHY_AUTONEGOTIATE_TIMEOUT 5000
     18 
     19 /* RTL8211x 1000BASE-T Control Register */
     20 #define MIIM_RTL8211x_CTRL1000T_MSCE BIT(12);
     21 #define MIIM_RTL8211x_CTRL1000T_MASTER BIT(11);
     22 
     23 /* RTL8211x PHY Status Register */
     24 #define MIIM_RTL8211x_PHY_STATUS       0x11
     25 #define MIIM_RTL8211x_PHYSTAT_SPEED    0xc000
     26 #define MIIM_RTL8211x_PHYSTAT_GBIT     0x8000
     27 #define MIIM_RTL8211x_PHYSTAT_100      0x4000
     28 #define MIIM_RTL8211x_PHYSTAT_DUPLEX   0x2000
     29 #define MIIM_RTL8211x_PHYSTAT_SPDDONE  0x0800
     30 #define MIIM_RTL8211x_PHYSTAT_LINK     0x0400
     31 
     32 /* RTL8211x PHY Interrupt Enable Register */
     33 #define MIIM_RTL8211x_PHY_INER         0x12
     34 #define MIIM_RTL8211x_PHY_INTR_ENA     0x9f01
     35 #define MIIM_RTL8211x_PHY_INTR_DIS     0x0000
     36 
     37 /* RTL8211x PHY Interrupt Status Register */
     38 #define MIIM_RTL8211x_PHY_INSR         0x13
     39 
     40 /* RTL8211F PHY Status Register */
     41 #define MIIM_RTL8211F_PHY_STATUS       0x1a
     42 #define MIIM_RTL8211F_AUTONEG_ENABLE   0x1000
     43 #define MIIM_RTL8211F_PHYSTAT_SPEED    0x0030
     44 #define MIIM_RTL8211F_PHYSTAT_GBIT     0x0020
     45 #define MIIM_RTL8211F_PHYSTAT_100      0x0010
     46 #define MIIM_RTL8211F_PHYSTAT_DUPLEX   0x0008
     47 #define MIIM_RTL8211F_PHYSTAT_SPDDONE  0x0800
     48 #define MIIM_RTL8211F_PHYSTAT_LINK     0x0004
     49 
     50 #define MIIM_RTL8211E_CONFREG           0x1c
     51 #define MIIM_RTL8211E_CONFREG_TXD		0x0002
     52 #define MIIM_RTL8211E_CONFREG_RXD		0x0004
     53 #define MIIM_RTL8211E_CONFREG_MAGIC		0xb400	/* Undocumented */
     54 
     55 #define MIIM_RTL8211E_EXT_PAGE_SELECT  0x1e
     56 
     57 #define MIIM_RTL8211F_PAGE_SELECT      0x1f
     58 #define MIIM_RTL8211F_TX_DELAY		0x100
     59 #define MIIM_RTL8211F_LCR		0x10
     60 
     61 static int rtl8211b_probe(struct phy_device *phydev)
     62 {
     63 #ifdef CONFIG_RTL8211X_PHY_FORCE_MASTER
     64 	phydev->flags |= PHY_RTL8211x_FORCE_MASTER;
     65 #endif
     66 
     67 	return 0;
     68 }
     69 
     70 static int rtl8211e_probe(struct phy_device *phydev)
     71 {
     72 #ifdef CONFIG_RTL8211E_PINE64_GIGABIT_FIX
     73 	phydev->flags |= PHY_RTL8211E_PINE64_GIGABIT_FIX;
     74 #endif
     75 
     76 	return 0;
     77 }
     78 
     79 /* RealTek RTL8211x */
     80 static int rtl8211x_config(struct phy_device *phydev)
     81 {
     82 	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
     83 
     84 	/* mask interrupt at init; if the interrupt is
     85 	 * needed indeed, it should be explicitly enabled
     86 	 */
     87 	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER,
     88 		  MIIM_RTL8211x_PHY_INTR_DIS);
     89 
     90 	if (phydev->flags & PHY_RTL8211x_FORCE_MASTER) {
     91 		unsigned int reg;
     92 
     93 		reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000);
     94 		/* force manual master/slave configuration */
     95 		reg |= MIIM_RTL8211x_CTRL1000T_MSCE;
     96 		/* force master mode */
     97 		reg |= MIIM_RTL8211x_CTRL1000T_MASTER;
     98 		phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, reg);
     99 	}
    100 	if (phydev->flags & PHY_RTL8211E_PINE64_GIGABIT_FIX) {
    101 		unsigned int reg;
    102 
    103 		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT,
    104 			  7);
    105 		phy_write(phydev, MDIO_DEVAD_NONE,
    106 			  MIIM_RTL8211E_EXT_PAGE_SELECT, 0xa4);
    107 		reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211E_CONFREG);
    108 		/* Ensure both internal delays are turned off */
    109 		reg &= ~(MIIM_RTL8211E_CONFREG_TXD | MIIM_RTL8211E_CONFREG_RXD);
    110 		/* Flip the magic undocumented bits */
    111 		reg |= MIIM_RTL8211E_CONFREG_MAGIC;
    112 		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211E_CONFREG, reg);
    113 		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT,
    114 			  0);
    115 	}
    116 	/* read interrupt status just to clear it */
    117 	phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER);
    118 
    119 	genphy_config_aneg(phydev);
    120 
    121 	return 0;
    122 }
    123 
    124 static int rtl8211f_config(struct phy_device *phydev)
    125 {
    126 	u16 reg;
    127 
    128 	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
    129 
    130 	phy_write(phydev, MDIO_DEVAD_NONE,
    131 		  MIIM_RTL8211F_PAGE_SELECT, 0xd08);
    132 	reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x11);
    133 
    134 	/* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */
    135 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
    136 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
    137 		reg |= MIIM_RTL8211F_TX_DELAY;
    138 	else
    139 		reg &= ~MIIM_RTL8211F_TX_DELAY;
    140 
    141 	phy_write(phydev, MDIO_DEVAD_NONE, 0x11, reg);
    142 	/* restore to default page 0 */
    143 	phy_write(phydev, MDIO_DEVAD_NONE,
    144 		  MIIM_RTL8211F_PAGE_SELECT, 0x0);
    145 
    146 	/* Set green LED for Link, yellow LED for Active */
    147 	phy_write(phydev, MDIO_DEVAD_NONE,
    148 		  MIIM_RTL8211F_PAGE_SELECT, 0xd04);
    149 	phy_write(phydev, MDIO_DEVAD_NONE, 0x10, 0x617f);
    150 	phy_write(phydev, MDIO_DEVAD_NONE,
    151 		  MIIM_RTL8211F_PAGE_SELECT, 0x0);
    152 
    153 	genphy_config_aneg(phydev);
    154 
    155 	return 0;
    156 }
    157 
    158 static int rtl8211x_parse_status(struct phy_device *phydev)
    159 {
    160 	unsigned int speed;
    161 	unsigned int mii_reg;
    162 
    163 	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_STATUS);
    164 
    165 	if (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) {
    166 		int i = 0;
    167 
    168 		/* in case of timeout ->link is cleared */
    169 		phydev->link = 1;
    170 		puts("Waiting for PHY realtime link");
    171 		while (!(mii_reg & MIIM_RTL8211x_PHYSTAT_SPDDONE)) {
    172 			/* Timeout reached ? */
    173 			if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
    174 				puts(" TIMEOUT !\n");
    175 				phydev->link = 0;
    176 				break;
    177 			}
    178 
    179 			if ((i++ % 1000) == 0)
    180 				putc('.');
    181 			udelay(1000);	/* 1 ms */
    182 			mii_reg = phy_read(phydev, MDIO_DEVAD_NONE,
    183 					MIIM_RTL8211x_PHY_STATUS);
    184 		}
    185 		puts(" done\n");
    186 		udelay(500000);	/* another 500 ms (results in faster booting) */
    187 	} else {
    188 		if (mii_reg & MIIM_RTL8211x_PHYSTAT_LINK)
    189 			phydev->link = 1;
    190 		else
    191 			phydev->link = 0;
    192 	}
    193 
    194 	if (mii_reg & MIIM_RTL8211x_PHYSTAT_DUPLEX)
    195 		phydev->duplex = DUPLEX_FULL;
    196 	else
    197 		phydev->duplex = DUPLEX_HALF;
    198 
    199 	speed = (mii_reg & MIIM_RTL8211x_PHYSTAT_SPEED);
    200 
    201 	switch (speed) {
    202 	case MIIM_RTL8211x_PHYSTAT_GBIT:
    203 		phydev->speed = SPEED_1000;
    204 		break;
    205 	case MIIM_RTL8211x_PHYSTAT_100:
    206 		phydev->speed = SPEED_100;
    207 		break;
    208 	default:
    209 		phydev->speed = SPEED_10;
    210 	}
    211 
    212 	return 0;
    213 }
    214 
    215 static int rtl8211f_parse_status(struct phy_device *phydev)
    216 {
    217 	unsigned int speed;
    218 	unsigned int mii_reg;
    219 	int i = 0;
    220 
    221 	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, 0xa43);
    222 	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PHY_STATUS);
    223 
    224 	phydev->link = 1;
    225 	while (!(mii_reg & MIIM_RTL8211F_PHYSTAT_LINK)) {
    226 		if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
    227 			puts(" TIMEOUT !\n");
    228 			phydev->link = 0;
    229 			break;
    230 		}
    231 
    232 		if ((i++ % 1000) == 0)
    233 			putc('.');
    234 		udelay(1000);
    235 		mii_reg = phy_read(phydev, MDIO_DEVAD_NONE,
    236 				   MIIM_RTL8211F_PHY_STATUS);
    237 	}
    238 
    239 	if (mii_reg & MIIM_RTL8211F_PHYSTAT_DUPLEX)
    240 		phydev->duplex = DUPLEX_FULL;
    241 	else
    242 		phydev->duplex = DUPLEX_HALF;
    243 
    244 	speed = (mii_reg & MIIM_RTL8211F_PHYSTAT_SPEED);
    245 
    246 	switch (speed) {
    247 	case MIIM_RTL8211F_PHYSTAT_GBIT:
    248 		phydev->speed = SPEED_1000;
    249 		break;
    250 	case MIIM_RTL8211F_PHYSTAT_100:
    251 		phydev->speed = SPEED_100;
    252 		break;
    253 	default:
    254 		phydev->speed = SPEED_10;
    255 	}
    256 
    257 	return 0;
    258 }
    259 
    260 static int rtl8211x_startup(struct phy_device *phydev)
    261 {
    262 	int ret;
    263 
    264 	/* Read the Status (2x to make sure link is right) */
    265 	ret = genphy_update_link(phydev);
    266 	if (ret)
    267 		return ret;
    268 
    269 	return rtl8211x_parse_status(phydev);
    270 }
    271 
    272 static int rtl8211e_startup(struct phy_device *phydev)
    273 {
    274 	int ret;
    275 
    276 	ret = genphy_update_link(phydev);
    277 	if (ret)
    278 		return ret;
    279 
    280 	return genphy_parse_link(phydev);
    281 }
    282 
    283 static int rtl8211f_startup(struct phy_device *phydev)
    284 {
    285 	int ret;
    286 
    287 	/* Read the Status (2x to make sure link is right) */
    288 	ret = genphy_update_link(phydev);
    289 	if (ret)
    290 		return ret;
    291 	/* Read the Status (2x to make sure link is right) */
    292 
    293 	return rtl8211f_parse_status(phydev);
    294 }
    295 
    296 /* Support for RTL8211B PHY */
    297 static struct phy_driver RTL8211B_driver = {
    298 	.name = "RealTek RTL8211B",
    299 	.uid = 0x1cc912,
    300 	.mask = 0xffffff,
    301 	.features = PHY_GBIT_FEATURES,
    302 	.probe = &rtl8211b_probe,
    303 	.config = &rtl8211x_config,
    304 	.startup = &rtl8211x_startup,
    305 	.shutdown = &genphy_shutdown,
    306 };
    307 
    308 /* Support for RTL8211E-VB-CG, RTL8211E-VL-CG and RTL8211EG-VB-CG PHYs */
    309 static struct phy_driver RTL8211E_driver = {
    310 	.name = "RealTek RTL8211E",
    311 	.uid = 0x1cc915,
    312 	.mask = 0xffffff,
    313 	.features = PHY_GBIT_FEATURES,
    314 	.probe = &rtl8211e_probe,
    315 	.config = &rtl8211x_config,
    316 	.startup = &rtl8211e_startup,
    317 	.shutdown = &genphy_shutdown,
    318 };
    319 
    320 /* Support for RTL8211DN PHY */
    321 static struct phy_driver RTL8211DN_driver = {
    322 	.name = "RealTek RTL8211DN",
    323 	.uid = 0x1cc914,
    324 	.mask = 0xffffff,
    325 	.features = PHY_GBIT_FEATURES,
    326 	.config = &rtl8211x_config,
    327 	.startup = &rtl8211x_startup,
    328 	.shutdown = &genphy_shutdown,
    329 };
    330 
    331 /* Support for RTL8211F PHY */
    332 static struct phy_driver RTL8211F_driver = {
    333 	.name = "RealTek RTL8211F",
    334 	.uid = 0x1cc916,
    335 	.mask = 0xffffff,
    336 	.features = PHY_GBIT_FEATURES,
    337 	.config = &rtl8211f_config,
    338 	.startup = &rtl8211f_startup,
    339 	.shutdown = &genphy_shutdown,
    340 };
    341 
    342 int phy_realtek_init(void)
    343 {
    344 	phy_register(&RTL8211B_driver);
    345 	phy_register(&RTL8211E_driver);
    346 	phy_register(&RTL8211F_driver);
    347 	phy_register(&RTL8211DN_driver);
    348 
    349 	return 0;
    350 }
    351