X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fphy%2Frealtek.c;h=8f1d75963259848490b66af7a4453e628b8177ab;hb=062aceb8bf4f47719b8035fd3d02dc1515caa63f;hp=35b934b8f0d0257cc0a947deb6aeb016dfa0eb39;hpb=020f67628d7f3e8f1c3ca93e8388d6b5ee128ec2;p=oweals%2Fu-boot.git diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 35b934b8f0..8f1d759632 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -1,22 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * RealTek PHY drivers * - * SPDX-License-Identifier: GPL-2.0+ - * * Copyright 2010-2011, 2015 Freescale Semiconductor, Inc. * author Andy Fleming * Copyright 2016 Karsten Merker */ -#include #include #include #include +#define PHY_RTL8211x_FORCE_MASTER BIT(1) +#define PHY_RTL8211E_PINE64_GIGABIT_FIX BIT(2) +#define PHY_RTL8211F_FORCE_EEE_RXC_ON BIT(3) + #define PHY_AUTONEGOTIATE_TIMEOUT 5000 /* RTL8211x 1000BASE-T Control Register */ #define MIIM_RTL8211x_CTRL1000T_MSCE BIT(12); -#define MIIM_RTL8211X_CTRL1000T_MASTER BIT(11); +#define MIIM_RTL8211x_CTRL1000T_MASTER BIT(11); /* RTL8211x PHY Status Register */ #define MIIM_RTL8211x_PHY_STATUS 0x11 @@ -45,10 +47,71 @@ #define MIIM_RTL8211F_PHYSTAT_SPDDONE 0x0800 #define MIIM_RTL8211F_PHYSTAT_LINK 0x0004 +#define MIIM_RTL8211E_CONFREG 0x1c +#define MIIM_RTL8211E_CONFREG_TXD 0x0002 +#define MIIM_RTL8211E_CONFREG_RXD 0x0004 +#define MIIM_RTL8211E_CONFREG_MAGIC 0xb400 /* Undocumented */ + +#define MIIM_RTL8211E_EXT_PAGE_SELECT 0x1e + #define MIIM_RTL8211F_PAGE_SELECT 0x1f #define MIIM_RTL8211F_TX_DELAY 0x100 #define MIIM_RTL8211F_LCR 0x10 +static int rtl8211f_phy_extread(struct phy_device *phydev, int addr, + int devaddr, int regnum) +{ + int oldpage = phy_read(phydev, MDIO_DEVAD_NONE, + MIIM_RTL8211F_PAGE_SELECT); + int val; + + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, devaddr); + val = phy_read(phydev, MDIO_DEVAD_NONE, regnum); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, oldpage); + + return val; +} + +static int rtl8211f_phy_extwrite(struct phy_device *phydev, int addr, + int devaddr, int regnum, u16 val) +{ + int oldpage = phy_read(phydev, MDIO_DEVAD_NONE, + MIIM_RTL8211F_PAGE_SELECT); + + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, devaddr); + phy_write(phydev, MDIO_DEVAD_NONE, regnum, val); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, oldpage); + + return 0; +} + +static int rtl8211b_probe(struct phy_device *phydev) +{ +#ifdef CONFIG_RTL8211X_PHY_FORCE_MASTER + phydev->flags |= PHY_RTL8211x_FORCE_MASTER; +#endif + + return 0; +} + +static int rtl8211e_probe(struct phy_device *phydev) +{ +#ifdef CONFIG_RTL8211E_PINE64_GIGABIT_FIX + phydev->flags |= PHY_RTL8211E_PINE64_GIGABIT_FIX; +#endif + + return 0; +} + +static int rtl8211f_probe(struct phy_device *phydev) +{ +#ifdef CONFIG_RTL8211F_PHY_FORCE_EEE_RXC_ON + phydev->flags |= PHY_RTL8211F_FORCE_EEE_RXC_ON; +#endif + + return 0; +} + /* RealTek RTL8211x */ static int rtl8211x_config(struct phy_device *phydev) { @@ -59,14 +122,33 @@ static int rtl8211x_config(struct phy_device *phydev) */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER, MIIM_RTL8211x_PHY_INTR_DIS); -#ifdef CONFIG_RTL8211X_PHY_FORCE_MASTER - unsigned int reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000); - /* force manual master/slave configuration */ - reg |= MIIM_RTL8211x_CTRL1000T_MSCE; - /* force master mode */ - reg |= MIIM_RTL8211X_CTRL1000T_MASTER; - phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, reg); -#endif + + if (phydev->flags & PHY_RTL8211x_FORCE_MASTER) { + unsigned int reg; + + reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000); + /* force manual master/slave configuration */ + reg |= MIIM_RTL8211x_CTRL1000T_MSCE; + /* force master mode */ + reg |= MIIM_RTL8211x_CTRL1000T_MASTER; + phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, reg); + } + if (phydev->flags & PHY_RTL8211E_PINE64_GIGABIT_FIX) { + unsigned int reg; + + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, + 7); + phy_write(phydev, MDIO_DEVAD_NONE, + MIIM_RTL8211E_EXT_PAGE_SELECT, 0xa4); + reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211E_CONFREG); + /* Ensure both internal delays are turned off */ + reg &= ~(MIIM_RTL8211E_CONFREG_TXD | MIIM_RTL8211E_CONFREG_RXD); + /* Flip the magic undocumented bits */ + reg |= MIIM_RTL8211E_CONFREG_MAGIC; + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211E_CONFREG, reg); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, + 0); + } /* read interrupt status just to clear it */ phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER); @@ -79,19 +161,31 @@ static int rtl8211f_config(struct phy_device *phydev) { u16 reg; + if (phydev->flags & PHY_RTL8211F_FORCE_EEE_RXC_ON) { + unsigned int reg; + + reg = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1); + reg &= ~MDIO_PCS_CTRL1_CLKSTOP_EN; + phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, reg); + } + phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); - if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { - /* enable TXDLY */ - phy_write(phydev, MDIO_DEVAD_NONE, - MIIM_RTL8211F_PAGE_SELECT, 0xd08); - reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x11); + phy_write(phydev, MDIO_DEVAD_NONE, + MIIM_RTL8211F_PAGE_SELECT, 0xd08); + reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x11); + + /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */ + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) reg |= MIIM_RTL8211F_TX_DELAY; - phy_write(phydev, MDIO_DEVAD_NONE, 0x11, reg); - /* restore to default page 0 */ - phy_write(phydev, MDIO_DEVAD_NONE, - MIIM_RTL8211F_PAGE_SELECT, 0x0); - } + else + reg &= ~MIIM_RTL8211F_TX_DELAY; + + phy_write(phydev, MDIO_DEVAD_NONE, 0x11, reg); + /* restore to default page 0 */ + phy_write(phydev, MDIO_DEVAD_NONE, + MIIM_RTL8211F_PAGE_SELECT, 0x0); /* Set green LED for Link, yellow LED for Active */ phy_write(phydev, MDIO_DEVAD_NONE, @@ -249,6 +343,7 @@ static struct phy_driver RTL8211B_driver = { .uid = 0x1cc912, .mask = 0xffffff, .features = PHY_GBIT_FEATURES, + .probe = &rtl8211b_probe, .config = &rtl8211x_config, .startup = &rtl8211x_startup, .shutdown = &genphy_shutdown, @@ -260,6 +355,7 @@ static struct phy_driver RTL8211E_driver = { .uid = 0x1cc915, .mask = 0xffffff, .features = PHY_GBIT_FEATURES, + .probe = &rtl8211e_probe, .config = &rtl8211x_config, .startup = &rtl8211e_startup, .shutdown = &genphy_shutdown, @@ -282,9 +378,12 @@ static struct phy_driver RTL8211F_driver = { .uid = 0x1cc916, .mask = 0xffffff, .features = PHY_GBIT_FEATURES, + .probe = &rtl8211f_probe, .config = &rtl8211f_config, .startup = &rtl8211f_startup, .shutdown = &genphy_shutdown, + .readext = &rtl8211f_phy_extread, + .writeext = &rtl8211f_phy_extwrite, }; int phy_realtek_init(void)