1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Marvell 88Q2XXX automotive 100BASE-T1/1000BASE-T1 PHY driver 4 * 5 * Derived from Marvell Q222x API 6 * 7 * Copyright (C) 2024 Liebherr-Electronics and Drives GmbH 8 */ 9 #include <linux/ethtool_netlink.h> 10 #include <linux/hwmon.h> 11 #include <linux/marvell_phy.h> 12 #include <linux/of.h> 13 #include <linux/phy.h> 14 15 #define PHY_ID_88Q2220_REVB0 (MARVELL_PHY_ID_88Q2220 | 0x1) 16 #define PHY_ID_88Q2220_REVB1 (MARVELL_PHY_ID_88Q2220 | 0x2) 17 #define PHY_ID_88Q2220_REVB2 (MARVELL_PHY_ID_88Q2220 | 0x3) 18 19 #define MDIO_MMD_AN_MV_STAT 32769 20 #define MDIO_MMD_AN_MV_STAT_ANEG 0x0100 21 #define MDIO_MMD_AN_MV_STAT_LOCAL_RX 0x1000 22 #define MDIO_MMD_AN_MV_STAT_REMOTE_RX 0x2000 23 #define MDIO_MMD_AN_MV_STAT_LOCAL_MASTER 0x4000 24 #define MDIO_MMD_AN_MV_STAT_MS_CONF_FAULT 0x8000 25 26 #define MDIO_MMD_AN_MV_STAT2 32794 27 #define MDIO_MMD_AN_MV_STAT2_AN_RESOLVED 0x0800 28 #define MDIO_MMD_AN_MV_STAT2_100BT1 0x2000 29 #define MDIO_MMD_AN_MV_STAT2_1000BT1 0x4000 30 31 #define MDIO_MMD_PCS_MV_RESET_CTRL 32768 32 #define MDIO_MMD_PCS_MV_RESET_CTRL_TX_DISABLE 0x8 33 34 #define MDIO_MMD_PCS_MV_INT_EN 32784 35 #define MDIO_MMD_PCS_MV_INT_EN_LINK_UP 0x0040 36 #define MDIO_MMD_PCS_MV_INT_EN_LINK_DOWN 0x0080 37 #define MDIO_MMD_PCS_MV_INT_EN_100BT1 0x1000 38 39 #define MDIO_MMD_PCS_MV_GPIO_INT_STAT 32785 40 #define MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_UP 0x0040 41 #define MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_DOWN 0x0080 42 #define MDIO_MMD_PCS_MV_GPIO_INT_STAT_100BT1_GEN 0x1000 43 44 #define MDIO_MMD_PCS_MV_GPIO_INT_CTRL 32787 45 #define MDIO_MMD_PCS_MV_GPIO_INT_CTRL_TRI_DIS 0x0800 46 47 #define MDIO_MMD_PCS_MV_LED_FUNC_CTRL 32790 48 #define MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LED_1_MASK GENMASK(7, 4) 49 #define MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LED_0_MASK GENMASK(3, 0) 50 #define MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LINK 0x0 /* Link established */ 51 #define MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LINK_RX_TX 0x1 /* Link established, blink for rx or tx activity */ 52 #define MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LINK_1000BT1 0x2 /* Blink 3x for 1000BT1 link established */ 53 #define MDIO_MMD_PCS_MV_LED_FUNC_CTRL_RX_TX_ON 0x3 /* Receive or transmit activity */ 54 #define MDIO_MMD_PCS_MV_LED_FUNC_CTRL_RX_TX 0x4 /* Blink on receive or transmit activity */ 55 #define MDIO_MMD_PCS_MV_LED_FUNC_CTRL_TX 0x5 /* Transmit activity */ 56 #define MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LINK_COPPER 0x6 /* Copper Link established */ 57 #define MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LINK_1000BT1_ON 0x7 /* 1000BT1 link established */ 58 #define MDIO_MMD_PCS_MV_LED_FUNC_CTRL_FORCE_OFF 0x8 /* Force off */ 59 #define MDIO_MMD_PCS_MV_LED_FUNC_CTRL_FORCE_ON 0x9 /* Force on */ 60 #define MDIO_MMD_PCS_MV_LED_FUNC_CTRL_FORCE_HIGHZ 0xa /* Force Hi-Z */ 61 #define MDIO_MMD_PCS_MV_LED_FUNC_CTRL_FORCE_BLINK 0xb /* Force blink */ 62 63 #define MDIO_MMD_PCS_MV_TEMP_SENSOR1 32833 64 #define MDIO_MMD_PCS_MV_TEMP_SENSOR1_RAW_INT 0x0001 65 #define MDIO_MMD_PCS_MV_TEMP_SENSOR1_INT 0x0040 66 #define MDIO_MMD_PCS_MV_TEMP_SENSOR1_INT_EN 0x0080 67 68 #define MDIO_MMD_PCS_MV_TEMP_SENSOR2 32834 69 #define MDIO_MMD_PCS_MV_TEMP_SENSOR2_DIS_MASK 0xc000 70 71 #define MDIO_MMD_PCS_MV_TEMP_SENSOR3 32835 72 #define MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK 0xff00 73 #define MDIO_MMD_PCS_MV_TEMP_SENSOR3_MASK 0x00ff 74 75 #define MDIO_MMD_PCS_MV_100BT1_STAT1 33032 76 #define MDIO_MMD_PCS_MV_100BT1_STAT1_IDLE_ERROR 0x00ff 77 #define MDIO_MMD_PCS_MV_100BT1_STAT1_JABBER 0x0100 78 #define MDIO_MMD_PCS_MV_100BT1_STAT1_LINK 0x0200 79 #define MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_RX 0x1000 80 #define MDIO_MMD_PCS_MV_100BT1_STAT1_REMOTE_RX 0x2000 81 #define MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_MASTER 0x4000 82 83 #define MDIO_MMD_PCS_MV_100BT1_STAT2 33033 84 #define MDIO_MMD_PCS_MV_100BT1_STAT2_JABBER 0x0001 85 #define MDIO_MMD_PCS_MV_100BT1_STAT2_POL 0x0002 86 #define MDIO_MMD_PCS_MV_100BT1_STAT2_LINK 0x0004 87 #define MDIO_MMD_PCS_MV_100BT1_STAT2_ANGE 0x0008 88 89 #define MDIO_MMD_PCS_MV_100BT1_INT_EN 33042 90 #define MDIO_MMD_PCS_MV_100BT1_INT_EN_LINKEVENT 0x0400 91 92 #define MDIO_MMD_PCS_MV_COPPER_INT_STAT 33043 93 #define MDIO_MMD_PCS_MV_COPPER_INT_STAT_LINKEVENT 0x0400 94 95 #define MDIO_MMD_PCS_MV_RX_STAT 33328 96 97 #define MDIO_MMD_PCS_MV_TDR_RESET 65226 98 #define MDIO_MMD_PCS_MV_TDR_RESET_TDR_RST 0x1000 99 100 #define MDIO_MMD_PCS_MV_TDR_OFF_SHORT_CABLE 65241 101 102 #define MDIO_MMD_PCS_MV_TDR_OFF_LONG_CABLE 65242 103 104 #define MDIO_MMD_PCS_MV_TDR_STATUS 65245 105 #define MDIO_MMD_PCS_MV_TDR_STATUS_MASK 0x0003 106 #define MDIO_MMD_PCS_MV_TDR_STATUS_OFF 0x0001 107 #define MDIO_MMD_PCS_MV_TDR_STATUS_ON 0x0002 108 #define MDIO_MMD_PCS_MV_TDR_STATUS_DIST_MASK 0xff00 109 #define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_MASK 0x00f0 110 #define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_SHORT 0x0030 111 #define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OPEN 0x00e0 112 #define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OK 0x0070 113 #define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_IN_PROGR 0x0080 114 #define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_NOISE 0x0050 115 116 #define MDIO_MMD_PCS_MV_TDR_OFF_CUTOFF 65246 117 118 #define MV88Q2XXX_LED_INDEX_TX_ENABLE 0 119 #define MV88Q2XXX_LED_INDEX_GPIO 1 120 121 struct mv88q2xxx_priv { 122 bool enable_temp; 123 bool enable_led0; 124 }; 125 126 struct mmd_val { 127 int devad; 128 u32 regnum; 129 u16 val; 130 }; 131 132 static const struct mmd_val mv88q2110_init_seq0[] = { 133 { MDIO_MMD_PCS, 0xffe4, 0x07b5 }, 134 { MDIO_MMD_PCS, 0xffe4, 0x06b6 }, 135 }; 136 137 static const struct mmd_val mv88q2110_init_seq1[] = { 138 { MDIO_MMD_PCS, 0xffde, 0x402f }, 139 { MDIO_MMD_PCS, 0xfe34, 0x4040 }, 140 { MDIO_MMD_PCS, 0xfe2a, 0x3c1d }, 141 { MDIO_MMD_PCS, 0xfe34, 0x0040 }, 142 { MDIO_MMD_AN, 0x8032, 0x0064 }, 143 { MDIO_MMD_AN, 0x8031, 0x0a01 }, 144 { MDIO_MMD_AN, 0x8031, 0x0c01 }, 145 { MDIO_MMD_PCS, 0xffdb, 0x0010 }, 146 }; 147 148 static const struct mmd_val mv88q222x_revb0_init_seq0[] = { 149 { MDIO_MMD_PCS, 0x8033, 0x6801 }, 150 { MDIO_MMD_AN, MDIO_AN_T1_CTRL, 0x0 }, 151 { MDIO_MMD_PMAPMD, MDIO_CTRL1, 152 MDIO_CTRL1_LPOWER | MDIO_PMA_CTRL1_SPEED1000 }, 153 { MDIO_MMD_PCS, 0xfe1b, 0x48 }, 154 { MDIO_MMD_PCS, 0xffe4, 0x6b6 }, 155 { MDIO_MMD_PMAPMD, MDIO_CTRL1, 0x0 }, 156 { MDIO_MMD_PCS, MDIO_CTRL1, 0x0 }, 157 }; 158 159 static const struct mmd_val mv88q222x_revb0_init_seq1[] = { 160 { MDIO_MMD_PCS, 0xfe79, 0x0 }, 161 { MDIO_MMD_PCS, 0xfe07, 0x125a }, 162 { MDIO_MMD_PCS, 0xfe09, 0x1288 }, 163 { MDIO_MMD_PCS, 0xfe08, 0x2588 }, 164 { MDIO_MMD_PCS, 0xfe11, 0x1105 }, 165 { MDIO_MMD_PCS, 0xfe72, 0x042c }, 166 { MDIO_MMD_PCS, 0xfbba, 0xcb2 }, 167 { MDIO_MMD_PCS, 0xfbbb, 0xc4a }, 168 { MDIO_MMD_AN, 0x8032, 0x2020 }, 169 { MDIO_MMD_AN, 0x8031, 0xa28 }, 170 { MDIO_MMD_AN, 0x8031, 0xc28 }, 171 { MDIO_MMD_PCS, 0xffdb, 0xfc10 }, 172 { MDIO_MMD_PCS, 0xfe1b, 0x58 }, 173 { MDIO_MMD_PCS, 0xfe79, 0x4 }, 174 { MDIO_MMD_PCS, 0xfe5f, 0xe8 }, 175 { MDIO_MMD_PCS, 0xfe05, 0x755c }, 176 }; 177 178 static const struct mmd_val mv88q222x_revb1_init_seq0[] = { 179 { MDIO_MMD_PCS, 0xffe4, 0x0007 }, 180 { MDIO_MMD_AN, MDIO_AN_T1_CTRL, 0x0 }, 181 { MDIO_MMD_PCS, 0xffe3, 0x7000 }, 182 { MDIO_MMD_PMAPMD, MDIO_CTRL1, 0x0840 }, 183 }; 184 185 static const struct mmd_val mv88q222x_revb2_init_seq0[] = { 186 { MDIO_MMD_PCS, 0xffe4, 0x0007 }, 187 { MDIO_MMD_AN, MDIO_AN_T1_CTRL, 0x0 }, 188 { MDIO_MMD_PMAPMD, MDIO_CTRL1, 0x0840 }, 189 }; 190 191 static const struct mmd_val mv88q222x_revb1_revb2_init_seq1[] = { 192 { MDIO_MMD_PCS, 0xfe07, 0x125a }, 193 { MDIO_MMD_PCS, 0xfe09, 0x1288 }, 194 { MDIO_MMD_PCS, 0xfe08, 0x2588 }, 195 { MDIO_MMD_PCS, 0xfe72, 0x042c }, 196 { MDIO_MMD_PCS, 0xffe4, 0x0071 }, 197 { MDIO_MMD_PCS, 0xffe4, 0x0001 }, 198 { MDIO_MMD_PCS, 0xfe1b, 0x0048 }, 199 { MDIO_MMD_PMAPMD, 0x0000, 0x0000 }, 200 { MDIO_MMD_PCS, 0x0000, 0x0000 }, 201 { MDIO_MMD_PCS, 0xffdb, 0xfc10 }, 202 { MDIO_MMD_PCS, 0xfe1b, 0x58 }, 203 { MDIO_MMD_PCS, 0xfcad, 0x030c }, 204 { MDIO_MMD_PCS, 0x8032, 0x6001 }, 205 { MDIO_MMD_PCS, 0xfdff, 0x05a5 }, 206 { MDIO_MMD_PCS, 0xfdec, 0xdbaf }, 207 { MDIO_MMD_PCS, 0xfcab, 0x1054 }, 208 { MDIO_MMD_PCS, 0xfcac, 0x1483 }, 209 { MDIO_MMD_PCS, 0x8033, 0xc801 }, 210 { MDIO_MMD_AN, 0x8032, 0x2020 }, 211 { MDIO_MMD_AN, 0x8031, 0xa28 }, 212 { MDIO_MMD_AN, 0x8031, 0xc28 }, 213 { MDIO_MMD_PCS, 0xfbba, 0x0cb2 }, 214 { MDIO_MMD_PCS, 0xfbbb, 0x0c4a }, 215 { MDIO_MMD_PCS, 0xfe5f, 0xe8 }, 216 { MDIO_MMD_PCS, 0xfe05, 0x755c }, 217 { MDIO_MMD_PCS, 0xfa20, 0x002a }, 218 { MDIO_MMD_PCS, 0xfe11, 0x1105 }, 219 }; 220 221 static int mv88q2xxx_write_mmd_vals(struct phy_device *phydev, 222 const struct mmd_val *vals, size_t len) 223 { 224 int ret; 225 226 for (; len; vals++, len--) { 227 ret = phy_write_mmd(phydev, vals->devad, vals->regnum, 228 vals->val); 229 if (ret < 0) 230 return ret; 231 } 232 233 return 0; 234 } 235 236 static int mv88q2xxx_soft_reset(struct phy_device *phydev) 237 { 238 int ret; 239 int val; 240 241 /* Enable RESET of DCL */ 242 if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed == SPEED_1000) { 243 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 0xfe1b, 0x48); 244 if (ret < 0) 245 return ret; 246 } 247 248 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_1000BT1_CTRL, 249 MDIO_PCS_1000BT1_CTRL_RESET); 250 if (ret < 0) 251 return ret; 252 253 ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS, 254 MDIO_PCS_1000BT1_CTRL, val, 255 !(val & MDIO_PCS_1000BT1_CTRL_RESET), 256 50000, 600000, true); 257 if (ret < 0) 258 return ret; 259 260 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 0xffe4, 0xc); 261 if (ret < 0) 262 return ret; 263 264 /* Disable RESET of DCL */ 265 if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed == SPEED_1000) 266 return phy_write_mmd(phydev, MDIO_MMD_PCS, 0xfe1b, 0x58); 267 268 return 0; 269 } 270 271 static int mv88q2xxx_read_link_gbit(struct phy_device *phydev) 272 { 273 int ret; 274 bool link = false; 275 276 /* Read vendor specific Auto-Negotiation status register to get local 277 * and remote receiver status according to software initialization 278 * guide. However, when not in polling mode the local and remote 279 * receiver status are not evaluated due to the Marvell 88Q2xxx APIs. 280 */ 281 ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT); 282 if (ret < 0) { 283 return ret; 284 } else if (((ret & MDIO_MMD_AN_MV_STAT_LOCAL_RX) && 285 (ret & MDIO_MMD_AN_MV_STAT_REMOTE_RX)) || 286 !phy_polling_mode(phydev)) { 287 /* The link state is latched low so that momentary link 288 * drops can be detected. Do not double-read the status 289 * in polling mode to detect such short link drops except 290 * the link was already down. 291 */ 292 if (!phy_polling_mode(phydev) || !phydev->link) { 293 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 294 MDIO_PCS_1000BT1_STAT); 295 if (ret < 0) 296 return ret; 297 else if (ret & MDIO_PCS_1000BT1_STAT_LINK) 298 link = true; 299 } 300 301 if (!link) { 302 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 303 MDIO_PCS_1000BT1_STAT); 304 if (ret < 0) 305 return ret; 306 else if (ret & MDIO_PCS_1000BT1_STAT_LINK) 307 link = true; 308 } 309 } 310 311 phydev->link = link; 312 313 return 0; 314 } 315 316 static int mv88q2xxx_read_link_100m(struct phy_device *phydev) 317 { 318 int ret; 319 320 /* The link state is latched low so that momentary link 321 * drops can be detected. Do not double-read the status 322 * in polling mode to detect such short link drops except 323 * the link was already down. In case we are not polling, 324 * we always read the realtime status. 325 */ 326 if (!phy_polling_mode(phydev)) { 327 phydev->link = false; 328 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 329 MDIO_MMD_PCS_MV_100BT1_STAT2); 330 if (ret < 0) 331 return ret; 332 333 if (ret & MDIO_MMD_PCS_MV_100BT1_STAT2_LINK) 334 phydev->link = true; 335 336 return 0; 337 } else if (!phydev->link) { 338 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 339 MDIO_MMD_PCS_MV_100BT1_STAT1); 340 if (ret < 0) 341 return ret; 342 else if (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LINK) 343 goto out; 344 } 345 346 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_100BT1_STAT1); 347 if (ret < 0) 348 return ret; 349 350 out: 351 /* Check if we have link and if the remote and local receiver are ok */ 352 if ((ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LINK) && 353 (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_RX) && 354 (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_REMOTE_RX)) 355 phydev->link = true; 356 else 357 phydev->link = false; 358 359 return 0; 360 } 361 362 static int mv88q2xxx_read_link(struct phy_device *phydev) 363 { 364 /* The 88Q2XXX PHYs do not have the PMA/PMD status register available, 365 * therefore we need to read the link status from the vendor specific 366 * registers depending on the speed. 367 */ 368 369 if (phydev->speed == SPEED_1000) 370 return mv88q2xxx_read_link_gbit(phydev); 371 else if (phydev->speed == SPEED_100) 372 return mv88q2xxx_read_link_100m(phydev); 373 374 phydev->link = false; 375 return 0; 376 } 377 378 static int mv88q2xxx_read_master_slave_state(struct phy_device *phydev) 379 { 380 int ret; 381 382 phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; 383 ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT); 384 if (ret < 0) 385 return ret; 386 387 if (ret & MDIO_MMD_AN_MV_STAT_LOCAL_MASTER) 388 phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; 389 else 390 phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; 391 392 return 0; 393 } 394 395 static int mv88q2xxx_read_aneg_speed(struct phy_device *phydev) 396 { 397 int ret; 398 399 phydev->speed = SPEED_UNKNOWN; 400 ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT2); 401 if (ret < 0) 402 return ret; 403 404 if (!(ret & MDIO_MMD_AN_MV_STAT2_AN_RESOLVED)) 405 return 0; 406 407 if (ret & MDIO_MMD_AN_MV_STAT2_100BT1) 408 phydev->speed = SPEED_100; 409 else if (ret & MDIO_MMD_AN_MV_STAT2_1000BT1) 410 phydev->speed = SPEED_1000; 411 412 return 0; 413 } 414 415 static int mv88q2xxx_read_status(struct phy_device *phydev) 416 { 417 int ret; 418 419 if (phydev->autoneg == AUTONEG_ENABLE) { 420 /* We have to get the negotiated speed first, otherwise we are 421 * not able to read the link. 422 */ 423 ret = mv88q2xxx_read_aneg_speed(phydev); 424 if (ret < 0) 425 return ret; 426 427 ret = mv88q2xxx_read_link(phydev); 428 if (ret < 0) 429 return ret; 430 431 ret = genphy_c45_read_lpa(phydev); 432 if (ret < 0) 433 return ret; 434 435 ret = genphy_c45_baset1_read_status(phydev); 436 if (ret < 0) 437 return ret; 438 439 ret = mv88q2xxx_read_master_slave_state(phydev); 440 if (ret < 0) 441 return ret; 442 443 phy_resolve_aneg_linkmode(phydev); 444 445 return 0; 446 } 447 448 ret = mv88q2xxx_read_link(phydev); 449 if (ret < 0) 450 return ret; 451 452 return genphy_c45_read_pma(phydev); 453 } 454 455 static int mv88q2xxx_get_features(struct phy_device *phydev) 456 { 457 int ret; 458 459 ret = genphy_c45_pma_read_abilities(phydev); 460 if (ret) 461 return ret; 462 463 /* We need to read the baset1 extended abilities manually because the 464 * PHY does not signalize it has the extended abilities register 465 * available. 466 */ 467 ret = genphy_c45_pma_baset1_read_abilities(phydev); 468 if (ret) 469 return ret; 470 471 return 0; 472 } 473 474 static int mv88q2xxx_config_aneg(struct phy_device *phydev) 475 { 476 int ret; 477 478 ret = genphy_c45_config_aneg(phydev); 479 if (ret) 480 return ret; 481 482 return phydev->drv->soft_reset(phydev); 483 } 484 485 static int mv88q2xxx_config_init(struct phy_device *phydev) 486 { 487 struct mv88q2xxx_priv *priv = phydev->priv; 488 int ret; 489 490 /* The 88Q2XXX PHYs do have the extended ability register available, but 491 * register MDIO_PMA_EXTABLE where they should signalize it does not 492 * work according to specification. Therefore, we force it here. 493 */ 494 phydev->pma_extable = MDIO_PMA_EXTABLE_BT1; 495 496 /* Configure interrupt with default settings, output is driven low for 497 * active interrupt and high for inactive. 498 */ 499 if (phy_interrupt_is_valid(phydev)) { 500 ret = phy_set_bits_mmd(phydev, MDIO_MMD_PCS, 501 MDIO_MMD_PCS_MV_GPIO_INT_CTRL, 502 MDIO_MMD_PCS_MV_GPIO_INT_CTRL_TRI_DIS); 503 if (ret < 0) 504 return ret; 505 } 506 507 /* Enable LED function and disable TX disable feature on LED/TX_ENABLE */ 508 if (priv->enable_led0) { 509 ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PCS, 510 MDIO_MMD_PCS_MV_RESET_CTRL, 511 MDIO_MMD_PCS_MV_RESET_CTRL_TX_DISABLE); 512 if (ret < 0) 513 return ret; 514 } 515 516 /* Enable temperature sense */ 517 if (priv->enable_temp) { 518 ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, 519 MDIO_MMD_PCS_MV_TEMP_SENSOR2, 520 MDIO_MMD_PCS_MV_TEMP_SENSOR2_DIS_MASK, 0); 521 if (ret < 0) 522 return ret; 523 } 524 525 return 0; 526 } 527 528 static int mv88q2xxx_get_sqi(struct phy_device *phydev) 529 { 530 int ret; 531 532 if (phydev->speed == SPEED_100) { 533 /* Read the SQI from the vendor specific receiver status 534 * register 535 */ 536 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 537 MDIO_MMD_PCS_MV_RX_STAT); 538 if (ret < 0) 539 return ret; 540 541 ret = ret >> 12; 542 } else { 543 /* Read from vendor specific registers, they are not documented 544 * but can be found in the Software Initialization Guide. Only 545 * revisions >= A0 are supported. 546 */ 547 ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, 0xfc5d, 0xff, 0xac); 548 if (ret < 0) 549 return ret; 550 551 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 0xfc88); 552 if (ret < 0) 553 return ret; 554 } 555 556 return ret & 0x0f; 557 } 558 559 static int mv88q2xxx_get_sqi_max(struct phy_device *phydev) 560 { 561 return 15; 562 } 563 564 static int mv88q2xxx_config_intr(struct phy_device *phydev) 565 { 566 int ret; 567 568 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 569 /* Enable interrupts for 1000BASE-T1 link up and down events 570 * and enable general interrupts for 100BASE-T1. 571 */ 572 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 573 MDIO_MMD_PCS_MV_INT_EN, 574 MDIO_MMD_PCS_MV_INT_EN_LINK_UP | 575 MDIO_MMD_PCS_MV_INT_EN_LINK_DOWN | 576 MDIO_MMD_PCS_MV_INT_EN_100BT1); 577 if (ret < 0) 578 return ret; 579 580 /* Enable interrupts for 100BASE-T1 link events */ 581 return phy_write_mmd(phydev, MDIO_MMD_PCS, 582 MDIO_MMD_PCS_MV_100BT1_INT_EN, 583 MDIO_MMD_PCS_MV_100BT1_INT_EN_LINKEVENT); 584 } else { 585 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 586 MDIO_MMD_PCS_MV_INT_EN, 0); 587 if (ret < 0) 588 return ret; 589 590 return phy_write_mmd(phydev, MDIO_MMD_PCS, 591 MDIO_MMD_PCS_MV_100BT1_INT_EN, 0); 592 } 593 } 594 595 static irqreturn_t mv88q2xxx_handle_interrupt(struct phy_device *phydev) 596 { 597 bool trigger_machine = false; 598 int irq; 599 600 /* Before we can acknowledge the 100BT1 general interrupt, that is in 601 * the 1000BT1 interrupt status register, we have to acknowledge any 602 * interrupts that are related to it. Therefore we read first the 100BT1 603 * interrupt status register, followed by reading the 1000BT1 interrupt 604 * status register. 605 */ 606 607 irq = phy_read_mmd(phydev, MDIO_MMD_PCS, 608 MDIO_MMD_PCS_MV_COPPER_INT_STAT); 609 if (irq < 0) { 610 phy_error(phydev); 611 return IRQ_NONE; 612 } 613 614 /* Check link status for 100BT1 */ 615 if (irq & MDIO_MMD_PCS_MV_COPPER_INT_STAT_LINKEVENT) 616 trigger_machine = true; 617 618 irq = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_GPIO_INT_STAT); 619 if (irq < 0) { 620 phy_error(phydev); 621 return IRQ_NONE; 622 } 623 624 /* Check link status for 1000BT1 */ 625 if ((irq & MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_UP) || 626 (irq & MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_DOWN)) 627 trigger_machine = true; 628 629 if (!trigger_machine) 630 return IRQ_NONE; 631 632 phy_trigger_machine(phydev); 633 634 return IRQ_HANDLED; 635 } 636 637 static int mv88q2xxx_suspend(struct phy_device *phydev) 638 { 639 int ret; 640 641 /* Disable PHY interrupts */ 642 if (phy_interrupt_is_valid(phydev)) { 643 phydev->interrupts = PHY_INTERRUPT_DISABLED; 644 ret = mv88q2xxx_config_intr(phydev); 645 if (ret) 646 return ret; 647 } 648 649 return phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, 650 MDIO_CTRL1_LPOWER); 651 } 652 653 static int mv88q2xxx_resume(struct phy_device *phydev) 654 { 655 int ret; 656 657 /* Enable PHY interrupts */ 658 if (phy_interrupt_is_valid(phydev)) { 659 phydev->interrupts = PHY_INTERRUPT_ENABLED; 660 ret = mv88q2xxx_config_intr(phydev); 661 if (ret) 662 return ret; 663 } 664 665 return phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, 666 MDIO_CTRL1_LPOWER); 667 } 668 669 #if IS_ENABLED(CONFIG_HWMON) 670 static const struct hwmon_channel_info * const mv88q2xxx_hwmon_info[] = { 671 HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_ALARM), 672 NULL 673 }; 674 675 static umode_t mv88q2xxx_hwmon_is_visible(const void *data, 676 enum hwmon_sensor_types type, 677 u32 attr, int channel) 678 { 679 switch (attr) { 680 case hwmon_temp_input: 681 return 0444; 682 case hwmon_temp_max: 683 return 0644; 684 case hwmon_temp_alarm: 685 return 0444; 686 default: 687 return 0; 688 } 689 } 690 691 static int mv88q2xxx_hwmon_read(struct device *dev, 692 enum hwmon_sensor_types type, 693 u32 attr, int channel, long *val) 694 { 695 struct phy_device *phydev = dev_get_drvdata(dev); 696 int ret; 697 698 switch (attr) { 699 case hwmon_temp_input: 700 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 701 MDIO_MMD_PCS_MV_TEMP_SENSOR3); 702 if (ret < 0) 703 return ret; 704 705 ret = FIELD_GET(MDIO_MMD_PCS_MV_TEMP_SENSOR3_MASK, ret); 706 *val = (ret - 75) * 1000; 707 return 0; 708 case hwmon_temp_max: 709 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 710 MDIO_MMD_PCS_MV_TEMP_SENSOR3); 711 if (ret < 0) 712 return ret; 713 714 ret = FIELD_GET(MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK, 715 ret); 716 *val = (ret - 75) * 1000; 717 return 0; 718 case hwmon_temp_alarm: 719 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 720 MDIO_MMD_PCS_MV_TEMP_SENSOR1); 721 if (ret < 0) 722 return ret; 723 724 *val = !!(ret & MDIO_MMD_PCS_MV_TEMP_SENSOR1_RAW_INT); 725 return 0; 726 default: 727 return -EOPNOTSUPP; 728 } 729 } 730 731 static int mv88q2xxx_hwmon_write(struct device *dev, 732 enum hwmon_sensor_types type, u32 attr, 733 int channel, long val) 734 { 735 struct phy_device *phydev = dev_get_drvdata(dev); 736 737 switch (attr) { 738 case hwmon_temp_max: 739 clamp_val(val, -75000, 180000); 740 val = (val / 1000) + 75; 741 val = FIELD_PREP(MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK, 742 val); 743 return phy_modify_mmd(phydev, MDIO_MMD_PCS, 744 MDIO_MMD_PCS_MV_TEMP_SENSOR3, 745 MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK, 746 val); 747 default: 748 return -EOPNOTSUPP; 749 } 750 } 751 752 static const struct hwmon_ops mv88q2xxx_hwmon_hwmon_ops = { 753 .is_visible = mv88q2xxx_hwmon_is_visible, 754 .read = mv88q2xxx_hwmon_read, 755 .write = mv88q2xxx_hwmon_write, 756 }; 757 758 static const struct hwmon_chip_info mv88q2xxx_hwmon_chip_info = { 759 .ops = &mv88q2xxx_hwmon_hwmon_ops, 760 .info = mv88q2xxx_hwmon_info, 761 }; 762 763 static int mv88q2xxx_hwmon_probe(struct phy_device *phydev) 764 { 765 struct mv88q2xxx_priv *priv = phydev->priv; 766 struct device *dev = &phydev->mdio.dev; 767 struct device *hwmon; 768 769 priv->enable_temp = true; 770 771 hwmon = devm_hwmon_device_register_with_info(dev, NULL, phydev, 772 &mv88q2xxx_hwmon_chip_info, 773 NULL); 774 775 return PTR_ERR_OR_ZERO(hwmon); 776 } 777 778 #else 779 static int mv88q2xxx_hwmon_probe(struct phy_device *phydev) 780 { 781 return 0; 782 } 783 #endif 784 785 #if IS_ENABLED(CONFIG_OF_MDIO) 786 static int mv88q2xxx_leds_probe(struct phy_device *phydev) 787 { 788 struct device_node *node = phydev->mdio.dev.of_node; 789 struct mv88q2xxx_priv *priv = phydev->priv; 790 struct device_node *leds; 791 int ret = 0; 792 u32 index; 793 794 if (!node) 795 return 0; 796 797 leds = of_get_child_by_name(node, "leds"); 798 if (!leds) 799 return 0; 800 801 for_each_available_child_of_node_scoped(leds, led) { 802 ret = of_property_read_u32(led, "reg", &index); 803 if (ret) 804 goto exit; 805 806 if (index > MV88Q2XXX_LED_INDEX_GPIO) { 807 ret = -EINVAL; 808 goto exit; 809 } 810 811 if (index == MV88Q2XXX_LED_INDEX_TX_ENABLE) 812 priv->enable_led0 = true; 813 } 814 815 exit: 816 of_node_put(leds); 817 818 return ret; 819 } 820 821 #else 822 static int mv88q2xxx_leds_probe(struct phy_device *phydev) 823 { 824 return 0; 825 } 826 #endif 827 828 static int mv88q2xxx_probe(struct phy_device *phydev) 829 { 830 struct mv88q2xxx_priv *priv; 831 832 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); 833 if (!priv) 834 return -ENOMEM; 835 836 phydev->priv = priv; 837 838 return 0; 839 } 840 841 static int mv88q222x_probe(struct phy_device *phydev) 842 { 843 int ret; 844 845 ret = mv88q2xxx_probe(phydev); 846 if (ret) 847 return ret; 848 849 ret = mv88q2xxx_leds_probe(phydev); 850 if (ret) 851 return ret; 852 853 return mv88q2xxx_hwmon_probe(phydev); 854 } 855 856 static int mv88q2110_config_init(struct phy_device *phydev) 857 { 858 int ret; 859 860 ret = mv88q2xxx_write_mmd_vals(phydev, mv88q2110_init_seq0, 861 ARRAY_SIZE(mv88q2110_init_seq0)); 862 if (ret < 0) 863 return ret; 864 865 usleep_range(5000, 10000); 866 867 ret = mv88q2xxx_write_mmd_vals(phydev, mv88q2110_init_seq1, 868 ARRAY_SIZE(mv88q2110_init_seq1)); 869 if (ret < 0) 870 return ret; 871 872 return mv88q2xxx_config_init(phydev); 873 } 874 875 static int mv88q222x_revb0_config_init(struct phy_device *phydev) 876 { 877 int ret; 878 879 ret = mv88q2xxx_write_mmd_vals(phydev, mv88q222x_revb0_init_seq0, 880 ARRAY_SIZE(mv88q222x_revb0_init_seq0)); 881 if (ret < 0) 882 return ret; 883 884 usleep_range(5000, 10000); 885 886 ret = mv88q2xxx_write_mmd_vals(phydev, mv88q222x_revb0_init_seq1, 887 ARRAY_SIZE(mv88q222x_revb0_init_seq1)); 888 if (ret < 0) 889 return ret; 890 891 return mv88q2xxx_config_init(phydev); 892 } 893 894 static int mv88q222x_revb1_revb2_config_init(struct phy_device *phydev) 895 { 896 bool is_rev_b1 = phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] == PHY_ID_88Q2220_REVB1; 897 int ret; 898 899 if (is_rev_b1) 900 ret = mv88q2xxx_write_mmd_vals(phydev, mv88q222x_revb1_init_seq0, 901 ARRAY_SIZE(mv88q222x_revb1_init_seq0)); 902 else 903 ret = mv88q2xxx_write_mmd_vals(phydev, mv88q222x_revb2_init_seq0, 904 ARRAY_SIZE(mv88q222x_revb2_init_seq0)); 905 if (ret < 0) 906 return ret; 907 908 usleep_range(3000, 5000); 909 910 ret = mv88q2xxx_write_mmd_vals(phydev, mv88q222x_revb1_revb2_init_seq1, 911 ARRAY_SIZE(mv88q222x_revb1_revb2_init_seq1)); 912 if (ret < 0) 913 return ret; 914 915 return mv88q2xxx_config_init(phydev); 916 } 917 918 static int mv88q222x_config_init(struct phy_device *phydev) 919 { 920 if (phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] == PHY_ID_88Q2220_REVB0) 921 return mv88q222x_revb0_config_init(phydev); 922 else 923 return mv88q222x_revb1_revb2_config_init(phydev); 924 } 925 926 static int mv88q222x_cable_test_start(struct phy_device *phydev) 927 { 928 int ret; 929 930 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 931 MDIO_MMD_PCS_MV_TDR_OFF_CUTOFF, 0x0058); 932 if (ret < 0) 933 return ret; 934 935 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 936 MDIO_MMD_PCS_MV_TDR_OFF_LONG_CABLE, 0x00eb); 937 if (ret < 0) 938 return ret; 939 940 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 941 MDIO_MMD_PCS_MV_TDR_OFF_SHORT_CABLE, 0x010e); 942 if (ret < 0) 943 return ret; 944 945 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_RESET, 946 0x0d90); 947 if (ret < 0) 948 return ret; 949 950 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_STATUS, 951 MDIO_MMD_PCS_MV_TDR_STATUS_ON); 952 if (ret < 0) 953 return ret; 954 955 /* According to the Marvell API the test is finished within 500 ms */ 956 msleep(500); 957 958 return 0; 959 } 960 961 static int mv88q222x_cable_test_get_status(struct phy_device *phydev, 962 bool *finished) 963 { 964 int ret, status; 965 u32 dist; 966 967 status = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_STATUS); 968 if (status < 0) 969 return status; 970 971 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_RESET, 972 MDIO_MMD_PCS_MV_TDR_RESET_TDR_RST | 0xd90); 973 if (ret < 0) 974 return ret; 975 976 /* Test could not be finished */ 977 if (FIELD_GET(MDIO_MMD_PCS_MV_TDR_STATUS_MASK, status) != 978 MDIO_MMD_PCS_MV_TDR_STATUS_OFF) 979 return -ETIMEDOUT; 980 981 *finished = true; 982 /* Fault length reported in meters, convert to centimeters */ 983 dist = FIELD_GET(MDIO_MMD_PCS_MV_TDR_STATUS_DIST_MASK, status) * 100; 984 switch (status & MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_MASK) { 985 case MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OPEN: 986 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 987 ETHTOOL_A_CABLE_RESULT_CODE_OPEN); 988 ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, 989 dist); 990 break; 991 case MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_SHORT: 992 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 993 ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT); 994 ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, 995 dist); 996 break; 997 case MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OK: 998 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 999 ETHTOOL_A_CABLE_RESULT_CODE_OK); 1000 break; 1001 default: 1002 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 1003 ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC); 1004 } 1005 1006 return 0; 1007 } 1008 1009 static int mv88q2xxx_led_mode(u8 index, unsigned long rules) 1010 { 1011 switch (rules) { 1012 case BIT(TRIGGER_NETDEV_LINK): 1013 return MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LINK; 1014 case BIT(TRIGGER_NETDEV_LINK_1000): 1015 return MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LINK_1000BT1_ON; 1016 case BIT(TRIGGER_NETDEV_TX): 1017 return MDIO_MMD_PCS_MV_LED_FUNC_CTRL_TX; 1018 case BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX): 1019 return MDIO_MMD_PCS_MV_LED_FUNC_CTRL_RX_TX; 1020 case BIT(TRIGGER_NETDEV_LINK) | BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX): 1021 return MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LINK_RX_TX; 1022 default: 1023 return -EOPNOTSUPP; 1024 } 1025 } 1026 1027 static int mv88q2xxx_led_hw_is_supported(struct phy_device *phydev, u8 index, 1028 unsigned long rules) 1029 { 1030 int mode; 1031 1032 mode = mv88q2xxx_led_mode(index, rules); 1033 if (mode < 0) 1034 return mode; 1035 1036 return 0; 1037 } 1038 1039 static int mv88q2xxx_led_hw_control_set(struct phy_device *phydev, u8 index, 1040 unsigned long rules) 1041 { 1042 int mode; 1043 1044 mode = mv88q2xxx_led_mode(index, rules); 1045 if (mode < 0) 1046 return mode; 1047 1048 if (index == MV88Q2XXX_LED_INDEX_TX_ENABLE) 1049 return phy_modify_mmd(phydev, MDIO_MMD_PCS, 1050 MDIO_MMD_PCS_MV_LED_FUNC_CTRL, 1051 MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LED_0_MASK, 1052 FIELD_PREP(MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LED_0_MASK, 1053 mode)); 1054 else 1055 return phy_modify_mmd(phydev, MDIO_MMD_PCS, 1056 MDIO_MMD_PCS_MV_LED_FUNC_CTRL, 1057 MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LED_1_MASK, 1058 FIELD_PREP(MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LED_1_MASK, 1059 mode)); 1060 } 1061 1062 static int mv88q2xxx_led_hw_control_get(struct phy_device *phydev, u8 index, 1063 unsigned long *rules) 1064 { 1065 int val; 1066 1067 val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_LED_FUNC_CTRL); 1068 if (val < 0) 1069 return val; 1070 1071 if (index == MV88Q2XXX_LED_INDEX_TX_ENABLE) 1072 val = FIELD_GET(MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LED_0_MASK, val); 1073 else 1074 val = FIELD_GET(MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LED_1_MASK, val); 1075 1076 switch (val) { 1077 case MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LINK: 1078 *rules = BIT(TRIGGER_NETDEV_LINK); 1079 break; 1080 case MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LINK_1000BT1_ON: 1081 *rules = BIT(TRIGGER_NETDEV_LINK_1000); 1082 break; 1083 case MDIO_MMD_PCS_MV_LED_FUNC_CTRL_TX: 1084 *rules = BIT(TRIGGER_NETDEV_TX); 1085 break; 1086 case MDIO_MMD_PCS_MV_LED_FUNC_CTRL_RX_TX: 1087 *rules = BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX); 1088 break; 1089 case MDIO_MMD_PCS_MV_LED_FUNC_CTRL_LINK_RX_TX: 1090 *rules = BIT(TRIGGER_NETDEV_LINK) | BIT(TRIGGER_NETDEV_TX) | 1091 BIT(TRIGGER_NETDEV_RX); 1092 break; 1093 default: 1094 *rules = 0; 1095 break; 1096 } 1097 1098 return 0; 1099 } 1100 1101 static struct phy_driver mv88q2xxx_driver[] = { 1102 { 1103 .phy_id = MARVELL_PHY_ID_88Q2110, 1104 .phy_id_mask = MARVELL_PHY_ID_MASK, 1105 .name = "mv88q2110", 1106 .probe = mv88q2xxx_probe, 1107 .get_features = mv88q2xxx_get_features, 1108 .config_aneg = mv88q2xxx_config_aneg, 1109 .config_init = mv88q2110_config_init, 1110 .read_status = mv88q2xxx_read_status, 1111 .soft_reset = mv88q2xxx_soft_reset, 1112 .set_loopback = genphy_c45_loopback, 1113 .get_sqi = mv88q2xxx_get_sqi, 1114 .get_sqi_max = mv88q2xxx_get_sqi_max, 1115 }, 1116 { 1117 .phy_id = MARVELL_PHY_ID_88Q2220, 1118 .phy_id_mask = MARVELL_PHY_ID_MASK, 1119 .name = "mv88q2220", 1120 .flags = PHY_POLL_CABLE_TEST, 1121 .probe = mv88q222x_probe, 1122 .get_features = mv88q2xxx_get_features, 1123 .config_aneg = mv88q2xxx_config_aneg, 1124 .aneg_done = genphy_c45_aneg_done, 1125 .config_init = mv88q222x_config_init, 1126 .read_status = mv88q2xxx_read_status, 1127 .soft_reset = mv88q2xxx_soft_reset, 1128 .config_intr = mv88q2xxx_config_intr, 1129 .handle_interrupt = mv88q2xxx_handle_interrupt, 1130 .set_loopback = genphy_c45_loopback, 1131 .cable_test_start = mv88q222x_cable_test_start, 1132 .cable_test_get_status = mv88q222x_cable_test_get_status, 1133 .get_sqi = mv88q2xxx_get_sqi, 1134 .get_sqi_max = mv88q2xxx_get_sqi_max, 1135 .suspend = mv88q2xxx_suspend, 1136 .resume = mv88q2xxx_resume, 1137 .led_hw_is_supported = mv88q2xxx_led_hw_is_supported, 1138 .led_hw_control_set = mv88q2xxx_led_hw_control_set, 1139 .led_hw_control_get = mv88q2xxx_led_hw_control_get, 1140 }, 1141 }; 1142 1143 module_phy_driver(mv88q2xxx_driver); 1144 1145 static const struct mdio_device_id __maybe_unused mv88q2xxx_tbl[] = { 1146 { MARVELL_PHY_ID_88Q2110, MARVELL_PHY_ID_MASK }, 1147 { MARVELL_PHY_ID_88Q2220, MARVELL_PHY_ID_MASK }, 1148 { /*sentinel*/ } 1149 }; 1150 MODULE_DEVICE_TABLE(mdio, mv88q2xxx_tbl); 1151 1152 MODULE_DESCRIPTION("Marvell 88Q2XXX 100/1000BASE-T1 Automotive Ethernet PHY driver"); 1153 MODULE_LICENSE("GPL"); 1154