Skip to content

Commit 85c2674

Browse files
committed
Merge branch 'add-support-for-dp83tg720s-phy'
Oleksij Rempel says: ==================== add support for DP83TG720S PHY ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents a25ebbf + cb80ee2 commit 85c2674

File tree

5 files changed

+277
-55
lines changed

5 files changed

+277
-55
lines changed

drivers/net/phy/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,19 @@ config DP83TD510_PHY
394394
Support for the DP83TD510 Ethernet 10Base-T1L PHY. This PHY supports
395395
a 10M single pair Ethernet connection for up to 1000 meter cable.
396396

397+
config DP83TG720_PHY
398+
tristate "Texas Instruments DP83TG720 Ethernet 1000Base-T1 PHY"
399+
help
400+
The DP83TG720S-Q1 is an automotive Ethernet physical layer
401+
transceiver compliant with IEEE 802.3bp and Open Alliance
402+
standards. It supports key functions necessary for
403+
transmitting and receiving data over both unshielded and
404+
shielded single twisted-pair cables. This device offers
405+
flexible xMII interface options, including support for both
406+
RGMII and SGMII MAC interfaces. It's suitable for applications
407+
requiring high-speed data transmission in automotive
408+
networking environments.
409+
397410
config VITESSE_PHY
398411
tristate "Vitesse PHYs"
399412
help

drivers/net/phy/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ obj-$(CONFIG_DP83867_PHY) += dp83867.o
5757
obj-$(CONFIG_DP83869_PHY) += dp83869.o
5858
obj-$(CONFIG_DP83TC811_PHY) += dp83tc811.o
5959
obj-$(CONFIG_DP83TD510_PHY) += dp83td510.o
60+
obj-$(CONFIG_DP83TG720_PHY) += dp83tg720.o
6061
obj-$(CONFIG_FIXED_PHY) += fixed_phy.o
6162
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
6263
obj-$(CONFIG_INTEL_XWAY_PHY) += intel-xway.o

drivers/net/phy/dp83tg720.c

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Driver for the Texas Instruments DP83TG720 PHY
3+
* Copyright (c) 2023 Pengutronix, Oleksij Rempel <[email protected]>
4+
*/
5+
#include <linux/bitfield.h>
6+
#include <linux/kernel.h>
7+
#include <linux/module.h>
8+
#include <linux/phy.h>
9+
10+
#define DP83TG720S_PHY_ID 0x2000a284
11+
12+
/* MDIO_MMD_VEND2 registers */
13+
#define DP83TG720S_MII_REG_10 0x10
14+
#define DP83TG720S_STS_MII_INT BIT(7)
15+
#define DP83TG720S_LINK_STATUS BIT(0)
16+
17+
#define DP83TG720S_PHY_RESET 0x1f
18+
#define DP83TG720S_HW_RESET BIT(15)
19+
20+
#define DP83TG720S_RGMII_DELAY_CTRL 0x602
21+
/* In RGMII mode, Enable or disable the internal delay for RXD */
22+
#define DP83TG720S_RGMII_RX_CLK_SEL BIT(1)
23+
/* In RGMII mode, Enable or disable the internal delay for TXD */
24+
#define DP83TG720S_RGMII_TX_CLK_SEL BIT(0)
25+
26+
#define DP83TG720S_SQI_REG_1 0x871
27+
#define DP83TG720S_SQI_OUT_WORST GENMASK(7, 5)
28+
#define DP83TG720S_SQI_OUT GENMASK(3, 1)
29+
30+
#define DP83TG720_SQI_MAX 7
31+
32+
static int dp83tg720_config_aneg(struct phy_device *phydev)
33+
{
34+
/* Autoneg is not supported and this PHY supports only one speed.
35+
* We need to care only about master/slave configuration if it was
36+
* changed by user.
37+
*/
38+
return genphy_c45_pma_baset1_setup_master_slave(phydev);
39+
}
40+
41+
static int dp83tg720_read_status(struct phy_device *phydev)
42+
{
43+
u16 phy_sts;
44+
int ret;
45+
46+
phydev->pause = 0;
47+
phydev->asym_pause = 0;
48+
49+
/* Most of Clause 45 registers are not present, so we can't use
50+
* genphy_c45_read_status() here.
51+
*/
52+
phy_sts = phy_read(phydev, DP83TG720S_MII_REG_10);
53+
phydev->link = !!(phy_sts & DP83TG720S_LINK_STATUS);
54+
if (!phydev->link) {
55+
/* According to the "DP83TC81x, DP83TG72x Software
56+
* Implementation Guide", the PHY needs to be reset after a
57+
* link loss or if no link is created after at least 100ms.
58+
*
59+
* Currently we are polling with the PHY_STATE_TIME (1000ms)
60+
* interval, which is still enough for not automotive use cases.
61+
*/
62+
ret = phy_init_hw(phydev);
63+
if (ret)
64+
return ret;
65+
66+
/* After HW reset we need to restore master/slave configuration.
67+
*/
68+
ret = dp83tg720_config_aneg(phydev);
69+
if (ret)
70+
return ret;
71+
72+
phydev->speed = SPEED_UNKNOWN;
73+
phydev->duplex = DUPLEX_UNKNOWN;
74+
} else {
75+
/* PMA/PMD control 1 register (Register 1.0) is present, but it
76+
* doesn't contain the link speed information.
77+
* So genphy_c45_read_pma() can't be used here.
78+
*/
79+
ret = genphy_c45_pma_baset1_read_master_slave(phydev);
80+
if (ret)
81+
return ret;
82+
83+
phydev->duplex = DUPLEX_FULL;
84+
phydev->speed = SPEED_1000;
85+
}
86+
87+
return 0;
88+
}
89+
90+
static int dp83tg720_get_sqi(struct phy_device *phydev)
91+
{
92+
int ret;
93+
94+
if (!phydev->link)
95+
return 0;
96+
97+
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_SQI_REG_1);
98+
if (ret < 0)
99+
return ret;
100+
101+
return FIELD_GET(DP83TG720S_SQI_OUT, ret);
102+
}
103+
104+
static int dp83tg720_get_sqi_max(struct phy_device *phydev)
105+
{
106+
return DP83TG720_SQI_MAX;
107+
}
108+
109+
static int dp83tg720_config_rgmii_delay(struct phy_device *phydev)
110+
{
111+
u16 rgmii_delay_mask;
112+
u16 rgmii_delay = 0;
113+
114+
switch (phydev->interface) {
115+
case PHY_INTERFACE_MODE_RGMII:
116+
rgmii_delay = 0;
117+
break;
118+
case PHY_INTERFACE_MODE_RGMII_ID:
119+
rgmii_delay = DP83TG720S_RGMII_RX_CLK_SEL |
120+
DP83TG720S_RGMII_TX_CLK_SEL;
121+
break;
122+
case PHY_INTERFACE_MODE_RGMII_RXID:
123+
rgmii_delay = DP83TG720S_RGMII_RX_CLK_SEL;
124+
break;
125+
case PHY_INTERFACE_MODE_RGMII_TXID:
126+
rgmii_delay = DP83TG720S_RGMII_TX_CLK_SEL;
127+
break;
128+
default:
129+
return 0;
130+
}
131+
132+
rgmii_delay_mask = DP83TG720S_RGMII_RX_CLK_SEL |
133+
DP83TG720S_RGMII_TX_CLK_SEL;
134+
135+
return phy_modify_mmd(phydev, MDIO_MMD_VEND2,
136+
DP83TG720S_RGMII_DELAY_CTRL, rgmii_delay_mask,
137+
rgmii_delay);
138+
}
139+
140+
static int dp83tg720_config_init(struct phy_device *phydev)
141+
{
142+
int ret;
143+
144+
/* Software Restart is not enough to recover from a link failure.
145+
* Using Hardware Reset instead.
146+
*/
147+
ret = phy_write(phydev, DP83TG720S_PHY_RESET, DP83TG720S_HW_RESET);
148+
if (ret)
149+
return ret;
150+
151+
/* Wait until MDC can be used again.
152+
* The wait value of one 1ms is documented in "DP83TG720S-Q1 1000BASE-T1
153+
* Automotive Ethernet PHY with SGMII and RGMII" datasheet.
154+
*/
155+
usleep_range(1000, 2000);
156+
157+
if (phy_interface_is_rgmii(phydev))
158+
return dp83tg720_config_rgmii_delay(phydev);
159+
160+
return 0;
161+
}
162+
163+
static struct phy_driver dp83tg720_driver[] = {
164+
{
165+
PHY_ID_MATCH_MODEL(DP83TG720S_PHY_ID),
166+
.name = "TI DP83TG720S",
167+
168+
.config_aneg = dp83tg720_config_aneg,
169+
.read_status = dp83tg720_read_status,
170+
.get_features = genphy_c45_pma_read_ext_abilities,
171+
.config_init = dp83tg720_config_init,
172+
.get_sqi = dp83tg720_get_sqi,
173+
.get_sqi_max = dp83tg720_get_sqi_max,
174+
175+
.suspend = genphy_suspend,
176+
.resume = genphy_resume,
177+
} };
178+
module_phy_driver(dp83tg720_driver);
179+
180+
static struct mdio_device_id __maybe_unused dp83tg720_tbl[] = {
181+
{ PHY_ID_MATCH_MODEL(DP83TG720S_PHY_ID) },
182+
{ }
183+
};
184+
MODULE_DEVICE_TABLE(mdio, dp83tg720_tbl);
185+
186+
MODULE_DESCRIPTION("Texas Instruments DP83TG720S PHY driver");
187+
MODULE_AUTHOR("Oleksij Rempel <[email protected]>");
188+
MODULE_LICENSE("GPL");

drivers/net/phy/phy-c45.c

Lines changed: 74 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,79 @@ int genphy_c45_pma_baset1_read_abilities(struct phy_device *phydev)
919919
}
920920
EXPORT_SYMBOL_GPL(genphy_c45_pma_baset1_read_abilities);
921921

922+
/**
923+
* genphy_c45_pma_read_ext_abilities - read supported link modes from PMA
924+
* @phydev: target phy_device struct
925+
*
926+
* Read the supported link modes from the PMA/PMD extended ability register
927+
* (Register 1.11).
928+
*/
929+
int genphy_c45_pma_read_ext_abilities(struct phy_device *phydev)
930+
{
931+
int val;
932+
933+
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE);
934+
if (val < 0)
935+
return val;
936+
937+
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
938+
phydev->supported,
939+
val & MDIO_PMA_EXTABLE_10GBLRM);
940+
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
941+
phydev->supported,
942+
val & MDIO_PMA_EXTABLE_10GBT);
943+
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
944+
phydev->supported,
945+
val & MDIO_PMA_EXTABLE_10GBKX4);
946+
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
947+
phydev->supported,
948+
val & MDIO_PMA_EXTABLE_10GBKR);
949+
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
950+
phydev->supported,
951+
val & MDIO_PMA_EXTABLE_1000BT);
952+
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
953+
phydev->supported,
954+
val & MDIO_PMA_EXTABLE_1000BKX);
955+
956+
linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
957+
phydev->supported,
958+
val & MDIO_PMA_EXTABLE_100BTX);
959+
linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
960+
phydev->supported,
961+
val & MDIO_PMA_EXTABLE_100BTX);
962+
963+
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
964+
phydev->supported,
965+
val & MDIO_PMA_EXTABLE_10BT);
966+
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
967+
phydev->supported,
968+
val & MDIO_PMA_EXTABLE_10BT);
969+
970+
if (val & MDIO_PMA_EXTABLE_NBT) {
971+
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
972+
MDIO_PMA_NG_EXTABLE);
973+
if (val < 0)
974+
return val;
975+
976+
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
977+
phydev->supported,
978+
val & MDIO_PMA_NG_EXTABLE_2_5GBT);
979+
980+
linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
981+
phydev->supported,
982+
val & MDIO_PMA_NG_EXTABLE_5GBT);
983+
}
984+
985+
if (val & MDIO_PMA_EXTABLE_BT1) {
986+
val = genphy_c45_pma_baset1_read_abilities(phydev);
987+
if (val < 0)
988+
return val;
989+
}
990+
991+
return 0;
992+
}
993+
EXPORT_SYMBOL_GPL(genphy_c45_pma_read_ext_abilities);
994+
922995
/**
923996
* genphy_c45_pma_read_abilities - read supported link modes from PMA
924997
* @phydev: target phy_device struct
@@ -962,63 +1035,9 @@ int genphy_c45_pma_read_abilities(struct phy_device *phydev)
9621035
val & MDIO_PMA_STAT2_10GBER);
9631036

9641037
if (val & MDIO_PMA_STAT2_EXTABLE) {
965-
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE);
1038+
val = genphy_c45_pma_read_ext_abilities(phydev);
9661039
if (val < 0)
9671040
return val;
968-
969-
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
970-
phydev->supported,
971-
val & MDIO_PMA_EXTABLE_10GBLRM);
972-
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
973-
phydev->supported,
974-
val & MDIO_PMA_EXTABLE_10GBT);
975-
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
976-
phydev->supported,
977-
val & MDIO_PMA_EXTABLE_10GBKX4);
978-
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
979-
phydev->supported,
980-
val & MDIO_PMA_EXTABLE_10GBKR);
981-
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
982-
phydev->supported,
983-
val & MDIO_PMA_EXTABLE_1000BT);
984-
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
985-
phydev->supported,
986-
val & MDIO_PMA_EXTABLE_1000BKX);
987-
988-
linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
989-
phydev->supported,
990-
val & MDIO_PMA_EXTABLE_100BTX);
991-
linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
992-
phydev->supported,
993-
val & MDIO_PMA_EXTABLE_100BTX);
994-
995-
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
996-
phydev->supported,
997-
val & MDIO_PMA_EXTABLE_10BT);
998-
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
999-
phydev->supported,
1000-
val & MDIO_PMA_EXTABLE_10BT);
1001-
1002-
if (val & MDIO_PMA_EXTABLE_NBT) {
1003-
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
1004-
MDIO_PMA_NG_EXTABLE);
1005-
if (val < 0)
1006-
return val;
1007-
1008-
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
1009-
phydev->supported,
1010-
val & MDIO_PMA_NG_EXTABLE_2_5GBT);
1011-
1012-
linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
1013-
phydev->supported,
1014-
val & MDIO_PMA_NG_EXTABLE_5GBT);
1015-
}
1016-
1017-
if (val & MDIO_PMA_EXTABLE_BT1) {
1018-
val = genphy_c45_pma_baset1_read_abilities(phydev);
1019-
if (val < 0)
1020-
return val;
1021-
}
10221041
}
10231042

10241043
/* This is optional functionality. If not supported, we may get an error

include/linux/phy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1866,6 +1866,7 @@ int genphy_c45_an_config_aneg(struct phy_device *phydev);
18661866
int genphy_c45_an_disable_aneg(struct phy_device *phydev);
18671867
int genphy_c45_read_mdix(struct phy_device *phydev);
18681868
int genphy_c45_pma_read_abilities(struct phy_device *phydev);
1869+
int genphy_c45_pma_read_ext_abilities(struct phy_device *phydev);
18691870
int genphy_c45_pma_baset1_read_abilities(struct phy_device *phydev);
18701871
int genphy_c45_read_eee_abilities(struct phy_device *phydev);
18711872
int genphy_c45_pma_baset1_read_master_slave(struct phy_device *phydev);

0 commit comments

Comments
 (0)