On Wed, Dec 06, 2023 at 12:11:18PM +0100, Oleksij Rempel wrote: > From: Oleksij Rempel <linux@xxxxxxxxxxxxxxxx> > > Add driver for TI DP83TG720 driver support. > > Even if the PHY is capable of creating a link on it's own. It needs > proper RGMII configuration and HW reset on link loss. > > Signed-off-by: Oleksij Rempel <o.rempel@xxxxxxxxxxxxxx> > --- > drivers/net/phy/Kconfig | 6 +++ > drivers/net/phy/Makefile | 1 + > drivers/net/phy/dp83tg720.c | 102 ++++++++++++++++++++++++++++++++++++ > 3 files changed, 109 insertions(+) > create mode 100644 drivers/net/phy/dp83tg720.c Applied, thanks Sascha > > diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig > index e95e2a3228..8e12671801 100644 > --- a/drivers/net/phy/Kconfig > +++ b/drivers/net/phy/Kconfig > @@ -35,6 +35,12 @@ config DP83TD510_PHY > Support for the DP83TD510 Ethernet 10Base-T1L PHY. This PHY supports > a 10M single pair Ethernet connection for up to 1000 meter cable. > > +config DP83TG720_PHY > + tristate "Texas Instruments DP83TG720 Ethernet 1000Base-T1 PHY" > + help > + Support for the DP83TG720 Ethernet 10000Base-T1 PHY. This PHY supports > + a 1000M single pair Ethernet. > + > config LXT_PHY > bool "Driver for the Intel LXT PHYs" > help > diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile > index 26e4ad884d..ce15e1bab7 100644 > --- a/drivers/net/phy/Makefile > +++ b/drivers/net/phy/Makefile > @@ -19,4 +19,5 @@ obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o > obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o > obj-$(CONFIG_DP83867_PHY) += dp83867.o > obj-$(CONFIG_DP83TD510_PHY) += dp83td510.o > +obj-$(CONFIG_DP83TG720_PHY) += dp83tg720.o > > diff --git a/drivers/net/phy/dp83tg720.c b/drivers/net/phy/dp83tg720.c > new file mode 100644 > index 0000000000..f0c6e29489 > --- /dev/null > +++ b/drivers/net/phy/dp83tg720.c > @@ -0,0 +1,102 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* Driver for the Texas Instruments DP83TG720 PHY > + * Copyright (c) 2023 Pengutronix, Oleksij Rempel <kernel@xxxxxxxxxxxxxx> > + */ > +#include <common.h> > +#include <linux/mdio.h> > +#include <linux/phy.h> > + > +#define DP83TG720S_PHY_ID 0x2000a284 > + > +/* MDIO_MMD_VEND2 registers */ > +#define DP83TG720S_MII_REG_10 0x10 > +#define DP83TG720S_LINK_STATUS BIT(0) > + > +#define DP83TG720S_RGMII_DELAY_CTRL 0x602 > +/* In RGMII mode, Enable or disable the internal delay for RXD */ > +#define DP83TG720S_RGMII_RX_CLK_SEL BIT(1) > +/* In RGMII mode, Enable or disable the internal delay for TXD */ > +#define DP83TG720S_RGMII_TX_CLK_SEL BIT(0) > + > +#define DP83TG720S_PHY_RESET 0x1f > +#define DP83TG720S_HW_RESET BIT(15) > + > +static int dp83tg720_config_rgmii_delay(struct phy_device *phydev) > +{ > + u16 rgmii_delay_mask; > + u16 rgmii_delay = 0; > + > + switch (phydev->interface) { > + case PHY_INTERFACE_MODE_RGMII: > + rgmii_delay = 0; > + break; > + case PHY_INTERFACE_MODE_RGMII_ID: > + rgmii_delay = DP83TG720S_RGMII_RX_CLK_SEL | > + DP83TG720S_RGMII_TX_CLK_SEL; > + break; > + case PHY_INTERFACE_MODE_RGMII_RXID: > + rgmii_delay = DP83TG720S_RGMII_RX_CLK_SEL; > + break; > + case PHY_INTERFACE_MODE_RGMII_TXID: > + rgmii_delay = DP83TG720S_RGMII_TX_CLK_SEL; > + break; > + default: > + return 0; > + } > + > + rgmii_delay_mask = DP83TG720S_RGMII_RX_CLK_SEL | > + DP83TG720S_RGMII_TX_CLK_SEL; > + > + return phy_modify_mmd(phydev, MDIO_MMD_VEND2, > + DP83TG720S_RGMII_DELAY_CTRL, rgmii_delay_mask, > + rgmii_delay); > +} > + > +static int dp83tg720_phy_init(struct phy_device *phydev) > +{ > + /* HW reset is needed to recover link if previous link was lost. SW > + * reset is not enough. > + */ > + phy_write(phydev, DP83TG720S_PHY_RESET, DP83TG720S_HW_RESET); > + > + phydev->supported = SUPPORTED_1000baseT_Full; > + phydev->advertising = SUPPORTED_1000baseT_Full; > + > + if (phy_interface_is_rgmii(phydev)) > + return dp83tg720_config_rgmii_delay(phydev); > + > + return 0; > +} > + > +static int dp83tg720_read_status(struct phy_device *phydev) > +{ > + u16 phy_sts; > + > + phy_sts = phy_read(phydev, DP83TG720S_MII_REG_10); > + phydev->link = !!(phy_sts & DP83TG720S_LINK_STATUS); > + if (!phydev->link) { > + phydev->speed = SPEED_UNKNOWN; > + phydev->duplex = DUPLEX_UNKNOWN; > + > + /* According to the "DP83TC81x, DP83TG72x Software > + * Implementation Guide", the PHY needs to be reset after a > + * link loss or if no link is created after at least 100ms. > + */ > + dp83tg720_phy_init(phydev); > + return 0; > + } > + > + phydev->duplex = DUPLEX_FULL; > + phydev->speed = SPEED_1000; > + > + return 0; > +} > + > +static struct phy_driver dp83tg720_driver[] = { > +{ > + PHY_ID_MATCH_MODEL(DP83TG720S_PHY_ID), > + .drv.name = "TI DP83TG720S", > + .read_status = dp83tg720_read_status, > + .config_init = dp83tg720_phy_init, > +} }; > +device_phy_drivers(dp83tg720_driver); > -- > 2.39.2 > > > -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |