xref: /linux/drivers/net/phy/dp83tg720.c (revision a3a02a52bcfcbcc4a637d4b68bf1bc391c9fad02)
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_LPS_CFG3			0x18c
21 /* Power modes are documented as bit fields but used as values */
22 /* Power Mode 0 is Normal mode */
23 #define DP83TG720S_LPS_CFG3_PWR_MODE_0		BIT(0)
24 
25 #define DP83TG720S_RGMII_DELAY_CTRL		0x602
26 /* In RGMII mode, Enable or disable the internal delay for RXD */
27 #define DP83TG720S_RGMII_RX_CLK_SEL		BIT(1)
28 /* In RGMII mode, Enable or disable the internal delay for TXD */
29 #define DP83TG720S_RGMII_TX_CLK_SEL		BIT(0)
30 
31 #define DP83TG720S_SQI_REG_1			0x871
32 #define DP83TG720S_SQI_OUT_WORST		GENMASK(7, 5)
33 #define DP83TG720S_SQI_OUT			GENMASK(3, 1)
34 
35 #define DP83TG720_SQI_MAX			7
36 
37 static int dp83tg720_config_aneg(struct phy_device *phydev)
38 {
39 	int ret;
40 
41 	/* Autoneg is not supported and this PHY supports only one speed.
42 	 * We need to care only about master/slave configuration if it was
43 	 * changed by user.
44 	 */
45 	ret = genphy_c45_pma_baset1_setup_master_slave(phydev);
46 	if (ret)
47 		return ret;
48 
49 	/* Re-read role configuration to make changes visible even if
50 	 * the link is in administrative down state.
51 	 */
52 	return genphy_c45_pma_baset1_read_master_slave(phydev);
53 }
54 
55 static int dp83tg720_read_status(struct phy_device *phydev)
56 {
57 	u16 phy_sts;
58 	int ret;
59 
60 	phydev->pause = 0;
61 	phydev->asym_pause = 0;
62 
63 	/* Most of Clause 45 registers are not present, so we can't use
64 	 * genphy_c45_read_status() here.
65 	 */
66 	phy_sts = phy_read(phydev, DP83TG720S_MII_REG_10);
67 	phydev->link = !!(phy_sts & DP83TG720S_LINK_STATUS);
68 	if (!phydev->link) {
69 		/* According to the "DP83TC81x, DP83TG72x Software
70 		 * Implementation Guide", the PHY needs to be reset after a
71 		 * link loss or if no link is created after at least 100ms.
72 		 *
73 		 * Currently we are polling with the PHY_STATE_TIME (1000ms)
74 		 * interval, which is still enough for not automotive use cases.
75 		 */
76 		ret = phy_init_hw(phydev);
77 		if (ret)
78 			return ret;
79 
80 		/* After HW reset we need to restore master/slave configuration.
81 		 * genphy_c45_pma_baset1_read_master_slave() call will be done
82 		 * by the dp83tg720_config_aneg() function.
83 		 */
84 		ret = dp83tg720_config_aneg(phydev);
85 		if (ret)
86 			return ret;
87 
88 		phydev->speed = SPEED_UNKNOWN;
89 		phydev->duplex = DUPLEX_UNKNOWN;
90 	} else {
91 		/* PMA/PMD control 1 register (Register 1.0) is present, but it
92 		 * doesn't contain the link speed information.
93 		 * So genphy_c45_read_pma() can't be used here.
94 		 */
95 		ret = genphy_c45_pma_baset1_read_master_slave(phydev);
96 		if (ret)
97 			return ret;
98 
99 		phydev->duplex = DUPLEX_FULL;
100 		phydev->speed = SPEED_1000;
101 	}
102 
103 	return 0;
104 }
105 
106 static int dp83tg720_get_sqi(struct phy_device *phydev)
107 {
108 	int ret;
109 
110 	if (!phydev->link)
111 		return 0;
112 
113 	ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_SQI_REG_1);
114 	if (ret < 0)
115 		return ret;
116 
117 	return FIELD_GET(DP83TG720S_SQI_OUT, ret);
118 }
119 
120 static int dp83tg720_get_sqi_max(struct phy_device *phydev)
121 {
122 	return DP83TG720_SQI_MAX;
123 }
124 
125 static int dp83tg720_config_rgmii_delay(struct phy_device *phydev)
126 {
127 	u16 rgmii_delay_mask;
128 	u16 rgmii_delay = 0;
129 
130 	switch (phydev->interface) {
131 	case PHY_INTERFACE_MODE_RGMII:
132 		rgmii_delay = 0;
133 		break;
134 	case PHY_INTERFACE_MODE_RGMII_ID:
135 		rgmii_delay = DP83TG720S_RGMII_RX_CLK_SEL |
136 				DP83TG720S_RGMII_TX_CLK_SEL;
137 		break;
138 	case PHY_INTERFACE_MODE_RGMII_RXID:
139 		rgmii_delay = DP83TG720S_RGMII_RX_CLK_SEL;
140 		break;
141 	case PHY_INTERFACE_MODE_RGMII_TXID:
142 		rgmii_delay = DP83TG720S_RGMII_TX_CLK_SEL;
143 		break;
144 	default:
145 		return 0;
146 	}
147 
148 	rgmii_delay_mask = DP83TG720S_RGMII_RX_CLK_SEL |
149 		DP83TG720S_RGMII_TX_CLK_SEL;
150 
151 	return phy_modify_mmd(phydev, MDIO_MMD_VEND2,
152 			      DP83TG720S_RGMII_DELAY_CTRL, rgmii_delay_mask,
153 			      rgmii_delay);
154 }
155 
156 static int dp83tg720_config_init(struct phy_device *phydev)
157 {
158 	int ret;
159 
160 	/* Software Restart is not enough to recover from a link failure.
161 	 * Using Hardware Reset instead.
162 	 */
163 	ret = phy_write(phydev, DP83TG720S_PHY_RESET, DP83TG720S_HW_RESET);
164 	if (ret)
165 		return ret;
166 
167 	/* Wait until MDC can be used again.
168 	 * The wait value of one 1ms is documented in "DP83TG720S-Q1 1000BASE-T1
169 	 * Automotive Ethernet PHY with SGMII and RGMII" datasheet.
170 	 */
171 	usleep_range(1000, 2000);
172 
173 	if (phy_interface_is_rgmii(phydev)) {
174 		ret = dp83tg720_config_rgmii_delay(phydev);
175 		if (ret)
176 			return ret;
177 	}
178 
179 	/* In case the PHY is bootstrapped in managed mode, we need to
180 	 * wake it.
181 	 */
182 	ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_LPS_CFG3,
183 			    DP83TG720S_LPS_CFG3_PWR_MODE_0);
184 	if (ret)
185 		return ret;
186 
187 	/* Make role configuration visible for ethtool on init and after
188 	 * rest.
189 	 */
190 	return genphy_c45_pma_baset1_read_master_slave(phydev);
191 }
192 
193 static struct phy_driver dp83tg720_driver[] = {
194 {
195 	PHY_ID_MATCH_MODEL(DP83TG720S_PHY_ID),
196 	.name		= "TI DP83TG720S",
197 
198 	.config_aneg	= dp83tg720_config_aneg,
199 	.read_status	= dp83tg720_read_status,
200 	.get_features	= genphy_c45_pma_read_ext_abilities,
201 	.config_init	= dp83tg720_config_init,
202 	.get_sqi	= dp83tg720_get_sqi,
203 	.get_sqi_max	= dp83tg720_get_sqi_max,
204 
205 	.suspend	= genphy_suspend,
206 	.resume		= genphy_resume,
207 } };
208 module_phy_driver(dp83tg720_driver);
209 
210 static struct mdio_device_id __maybe_unused dp83tg720_tbl[] = {
211 	{ PHY_ID_MATCH_MODEL(DP83TG720S_PHY_ID) },
212 	{ }
213 };
214 MODULE_DEVICE_TABLE(mdio, dp83tg720_tbl);
215 
216 MODULE_DESCRIPTION("Texas Instruments DP83TG720S PHY driver");
217 MODULE_AUTHOR("Oleksij Rempel <kernel@pengutronix.de>");
218 MODULE_LICENSE("GPL");
219