xref: /linux/drivers/net/phy/dp83tg720.c (revision e6a901a00822659181c93c86d8bbc2a17779fddc)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Driver for the Texas Instruments DP83TG720 PHY
3  * Copyright (c) 2023 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
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 <kernel@pengutronix.de>");
188 MODULE_LICENSE("GPL");
189