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/ethtool_netlink.h> 7 #include <linux/kernel.h> 8 #include <linux/module.h> 9 #include <linux/phy.h> 10 11 #include "open_alliance_helpers.h" 12 13 #define DP83TG720S_PHY_ID 0x2000a284 14 15 /* MDIO_MMD_VEND2 registers */ 16 #define DP83TG720S_MII_REG_10 0x10 17 #define DP83TG720S_STS_MII_INT BIT(7) 18 #define DP83TG720S_LINK_STATUS BIT(0) 19 20 /* TDR Configuration Register (0x1E) */ 21 #define DP83TG720S_TDR_CFG 0x1e 22 /* 1b = TDR start, 0b = No TDR */ 23 #define DP83TG720S_TDR_START BIT(15) 24 /* 1b = TDR auto on link down, 0b = Manual TDR start */ 25 #define DP83TG720S_CFG_TDR_AUTO_RUN BIT(14) 26 /* 1b = TDR done, 0b = TDR in progress */ 27 #define DP83TG720S_TDR_DONE BIT(1) 28 /* 1b = TDR fail, 0b = TDR success */ 29 #define DP83TG720S_TDR_FAIL BIT(0) 30 31 #define DP83TG720S_PHY_RESET 0x1f 32 #define DP83TG720S_HW_RESET BIT(15) 33 34 #define DP83TG720S_LPS_CFG3 0x18c 35 /* Power modes are documented as bit fields but used as values */ 36 /* Power Mode 0 is Normal mode */ 37 #define DP83TG720S_LPS_CFG3_PWR_MODE_0 BIT(0) 38 39 /* Open Aliance 1000BaseT1 compatible HDD.TDR Fault Status Register */ 40 #define DP83TG720S_TDR_FAULT_STATUS 0x30f 41 42 /* Register 0x0301: TDR Configuration 2 */ 43 #define DP83TG720S_TDR_CFG2 0x301 44 45 /* Register 0x0303: TDR Configuration 3 */ 46 #define DP83TG720S_TDR_CFG3 0x303 47 48 /* Register 0x0304: TDR Configuration 4 */ 49 #define DP83TG720S_TDR_CFG4 0x304 50 51 /* Register 0x0405: Unknown Register */ 52 #define DP83TG720S_UNKNOWN_0405 0x405 53 54 /* Register 0x0576: TDR Master Link Down Control */ 55 #define DP83TG720S_TDR_MASTER_LINK_DOWN 0x576 56 57 #define DP83TG720S_RGMII_DELAY_CTRL 0x602 58 /* In RGMII mode, Enable or disable the internal delay for RXD */ 59 #define DP83TG720S_RGMII_RX_CLK_SEL BIT(1) 60 /* In RGMII mode, Enable or disable the internal delay for TXD */ 61 #define DP83TG720S_RGMII_TX_CLK_SEL BIT(0) 62 63 /* Register 0x083F: Unknown Register */ 64 #define DP83TG720S_UNKNOWN_083F 0x83f 65 66 #define DP83TG720S_SQI_REG_1 0x871 67 #define DP83TG720S_SQI_OUT_WORST GENMASK(7, 5) 68 #define DP83TG720S_SQI_OUT GENMASK(3, 1) 69 70 #define DP83TG720_SQI_MAX 7 71 72 /** 73 * dp83tg720_cable_test_start - Start the cable test for the DP83TG720 PHY. 74 * @phydev: Pointer to the phy_device structure. 75 * 76 * This sequence is based on the documented procedure for the DP83TG720 PHY. 77 * 78 * Returns: 0 on success, a negative error code on failure. 79 */ 80 static int dp83tg720_cable_test_start(struct phy_device *phydev) 81 { 82 int ret; 83 84 /* Initialize the PHY to run the TDR test as described in the 85 * "DP83TG720S-Q1: Configuring for Open Alliance Specification 86 * Compliance (Rev. B)" application note. 87 * Most of the registers are not documented. Some of register names 88 * are guessed by comparing the register offsets with the DP83TD510E. 89 */ 90 91 /* Force master link down */ 92 ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, 93 DP83TG720S_TDR_MASTER_LINK_DOWN, 0x0400); 94 if (ret) 95 return ret; 96 97 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_TDR_CFG2, 98 0xa008); 99 if (ret) 100 return ret; 101 102 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_TDR_CFG3, 103 0x0928); 104 if (ret) 105 return ret; 106 107 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_TDR_CFG4, 108 0x0004); 109 if (ret) 110 return ret; 111 112 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_UNKNOWN_0405, 113 0x6400); 114 if (ret) 115 return ret; 116 117 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_UNKNOWN_083F, 118 0x3003); 119 if (ret) 120 return ret; 121 122 /* Start the TDR */ 123 ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_TDR_CFG, 124 DP83TG720S_TDR_START); 125 if (ret) 126 return ret; 127 128 return 0; 129 } 130 131 /** 132 * dp83tg720_cable_test_get_status - Get the status of the cable test for the 133 * DP83TG720 PHY. 134 * @phydev: Pointer to the phy_device structure. 135 * @finished: Pointer to a boolean that indicates whether the test is finished. 136 * 137 * The function sets the @finished flag to true if the test is complete. 138 * 139 * Returns: 0 on success or a negative error code on failure. 140 */ 141 static int dp83tg720_cable_test_get_status(struct phy_device *phydev, 142 bool *finished) 143 { 144 int ret, stat; 145 146 *finished = false; 147 148 /* Read the TDR status */ 149 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_TDR_CFG); 150 if (ret < 0) 151 return ret; 152 153 /* Check if the TDR test is done */ 154 if (!(ret & DP83TG720S_TDR_DONE)) 155 return 0; 156 157 /* Check for TDR test failure */ 158 if (!(ret & DP83TG720S_TDR_FAIL)) { 159 int location; 160 161 /* Read fault status */ 162 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, 163 DP83TG720S_TDR_FAULT_STATUS); 164 if (ret < 0) 165 return ret; 166 167 /* Get fault type */ 168 stat = oa_1000bt1_get_ethtool_cable_result_code(ret); 169 170 /* Determine fault location */ 171 location = oa_1000bt1_get_tdr_distance(ret); 172 if (location > 0) 173 ethnl_cable_test_fault_length(phydev, 174 ETHTOOL_A_CABLE_PAIR_A, 175 location); 176 } else { 177 /* Active link partner or other issues */ 178 stat = ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; 179 } 180 181 *finished = true; 182 183 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, stat); 184 185 return phy_init_hw(phydev); 186 } 187 188 static int dp83tg720_config_aneg(struct phy_device *phydev) 189 { 190 int ret; 191 192 /* Autoneg is not supported and this PHY supports only one speed. 193 * We need to care only about master/slave configuration if it was 194 * changed by user. 195 */ 196 ret = genphy_c45_pma_baset1_setup_master_slave(phydev); 197 if (ret) 198 return ret; 199 200 /* Re-read role configuration to make changes visible even if 201 * the link is in administrative down state. 202 */ 203 return genphy_c45_pma_baset1_read_master_slave(phydev); 204 } 205 206 static int dp83tg720_read_status(struct phy_device *phydev) 207 { 208 u16 phy_sts; 209 int ret; 210 211 phydev->pause = 0; 212 phydev->asym_pause = 0; 213 214 /* Most of Clause 45 registers are not present, so we can't use 215 * genphy_c45_read_status() here. 216 */ 217 phy_sts = phy_read(phydev, DP83TG720S_MII_REG_10); 218 phydev->link = !!(phy_sts & DP83TG720S_LINK_STATUS); 219 if (!phydev->link) { 220 /* According to the "DP83TC81x, DP83TG72x Software 221 * Implementation Guide", the PHY needs to be reset after a 222 * link loss or if no link is created after at least 100ms. 223 * 224 * Currently we are polling with the PHY_STATE_TIME (1000ms) 225 * interval, which is still enough for not automotive use cases. 226 */ 227 ret = phy_init_hw(phydev); 228 if (ret) 229 return ret; 230 231 /* After HW reset we need to restore master/slave configuration. 232 * genphy_c45_pma_baset1_read_master_slave() call will be done 233 * by the dp83tg720_config_aneg() function. 234 */ 235 ret = dp83tg720_config_aneg(phydev); 236 if (ret) 237 return ret; 238 239 phydev->speed = SPEED_UNKNOWN; 240 phydev->duplex = DUPLEX_UNKNOWN; 241 } else { 242 /* PMA/PMD control 1 register (Register 1.0) is present, but it 243 * doesn't contain the link speed information. 244 * So genphy_c45_read_pma() can't be used here. 245 */ 246 ret = genphy_c45_pma_baset1_read_master_slave(phydev); 247 if (ret) 248 return ret; 249 250 phydev->duplex = DUPLEX_FULL; 251 phydev->speed = SPEED_1000; 252 } 253 254 return 0; 255 } 256 257 static int dp83tg720_get_sqi(struct phy_device *phydev) 258 { 259 int ret; 260 261 if (!phydev->link) 262 return 0; 263 264 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_SQI_REG_1); 265 if (ret < 0) 266 return ret; 267 268 return FIELD_GET(DP83TG720S_SQI_OUT, ret); 269 } 270 271 static int dp83tg720_get_sqi_max(struct phy_device *phydev) 272 { 273 return DP83TG720_SQI_MAX; 274 } 275 276 static int dp83tg720_config_rgmii_delay(struct phy_device *phydev) 277 { 278 u16 rgmii_delay_mask; 279 u16 rgmii_delay = 0; 280 281 switch (phydev->interface) { 282 case PHY_INTERFACE_MODE_RGMII: 283 rgmii_delay = 0; 284 break; 285 case PHY_INTERFACE_MODE_RGMII_ID: 286 rgmii_delay = DP83TG720S_RGMII_RX_CLK_SEL | 287 DP83TG720S_RGMII_TX_CLK_SEL; 288 break; 289 case PHY_INTERFACE_MODE_RGMII_RXID: 290 rgmii_delay = DP83TG720S_RGMII_RX_CLK_SEL; 291 break; 292 case PHY_INTERFACE_MODE_RGMII_TXID: 293 rgmii_delay = DP83TG720S_RGMII_TX_CLK_SEL; 294 break; 295 default: 296 return 0; 297 } 298 299 rgmii_delay_mask = DP83TG720S_RGMII_RX_CLK_SEL | 300 DP83TG720S_RGMII_TX_CLK_SEL; 301 302 return phy_modify_mmd(phydev, MDIO_MMD_VEND2, 303 DP83TG720S_RGMII_DELAY_CTRL, rgmii_delay_mask, 304 rgmii_delay); 305 } 306 307 static int dp83tg720_config_init(struct phy_device *phydev) 308 { 309 int ret; 310 311 /* Software Restart is not enough to recover from a link failure. 312 * Using Hardware Reset instead. 313 */ 314 ret = phy_write(phydev, DP83TG720S_PHY_RESET, DP83TG720S_HW_RESET); 315 if (ret) 316 return ret; 317 318 /* Wait until MDC can be used again. 319 * The wait value of one 1ms is documented in "DP83TG720S-Q1 1000BASE-T1 320 * Automotive Ethernet PHY with SGMII and RGMII" datasheet. 321 */ 322 usleep_range(1000, 2000); 323 324 if (phy_interface_is_rgmii(phydev)) { 325 ret = dp83tg720_config_rgmii_delay(phydev); 326 if (ret) 327 return ret; 328 } 329 330 /* In case the PHY is bootstrapped in managed mode, we need to 331 * wake it. 332 */ 333 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_LPS_CFG3, 334 DP83TG720S_LPS_CFG3_PWR_MODE_0); 335 if (ret) 336 return ret; 337 338 /* Make role configuration visible for ethtool on init and after 339 * rest. 340 */ 341 return genphy_c45_pma_baset1_read_master_slave(phydev); 342 } 343 344 static struct phy_driver dp83tg720_driver[] = { 345 { 346 PHY_ID_MATCH_MODEL(DP83TG720S_PHY_ID), 347 .name = "TI DP83TG720S", 348 349 .flags = PHY_POLL_CABLE_TEST, 350 .config_aneg = dp83tg720_config_aneg, 351 .read_status = dp83tg720_read_status, 352 .get_features = genphy_c45_pma_read_ext_abilities, 353 .config_init = dp83tg720_config_init, 354 .get_sqi = dp83tg720_get_sqi, 355 .get_sqi_max = dp83tg720_get_sqi_max, 356 .cable_test_start = dp83tg720_cable_test_start, 357 .cable_test_get_status = dp83tg720_cable_test_get_status, 358 359 .suspend = genphy_suspend, 360 .resume = genphy_resume, 361 } }; 362 module_phy_driver(dp83tg720_driver); 363 364 static struct mdio_device_id __maybe_unused dp83tg720_tbl[] = { 365 { PHY_ID_MATCH_MODEL(DP83TG720S_PHY_ID) }, 366 { } 367 }; 368 MODULE_DEVICE_TABLE(mdio, dp83tg720_tbl); 369 370 MODULE_DESCRIPTION("Texas Instruments DP83TG720S PHY driver"); 371 MODULE_AUTHOR("Oleksij Rempel <kernel@pengutronix.de>"); 372 MODULE_LICENSE("GPL"); 373