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/marvell_phy.h> 11 #include <linux/phy.h> 12 #include <linux/hwmon.h> 13 14 #define PHY_ID_88Q2220_REVB0 (MARVELL_PHY_ID_88Q2220 | 0x1) 15 16 #define MDIO_MMD_AN_MV_STAT 32769 17 #define MDIO_MMD_AN_MV_STAT_ANEG 0x0100 18 #define MDIO_MMD_AN_MV_STAT_LOCAL_RX 0x1000 19 #define MDIO_MMD_AN_MV_STAT_REMOTE_RX 0x2000 20 #define MDIO_MMD_AN_MV_STAT_LOCAL_MASTER 0x4000 21 #define MDIO_MMD_AN_MV_STAT_MS_CONF_FAULT 0x8000 22 23 #define MDIO_MMD_AN_MV_STAT2 32794 24 #define MDIO_MMD_AN_MV_STAT2_AN_RESOLVED 0x0800 25 #define MDIO_MMD_AN_MV_STAT2_100BT1 0x2000 26 #define MDIO_MMD_AN_MV_STAT2_1000BT1 0x4000 27 28 #define MDIO_MMD_PCS_MV_INT_EN 32784 29 #define MDIO_MMD_PCS_MV_INT_EN_LINK_UP 0x0040 30 #define MDIO_MMD_PCS_MV_INT_EN_LINK_DOWN 0x0080 31 #define MDIO_MMD_PCS_MV_INT_EN_100BT1 0x1000 32 33 #define MDIO_MMD_PCS_MV_GPIO_INT_STAT 32785 34 #define MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_UP 0x0040 35 #define MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_DOWN 0x0080 36 #define MDIO_MMD_PCS_MV_GPIO_INT_STAT_100BT1_GEN 0x1000 37 38 #define MDIO_MMD_PCS_MV_GPIO_INT_CTRL 32787 39 #define MDIO_MMD_PCS_MV_GPIO_INT_CTRL_TRI_DIS 0x0800 40 41 #define MDIO_MMD_PCS_MV_TEMP_SENSOR1 32833 42 #define MDIO_MMD_PCS_MV_TEMP_SENSOR1_RAW_INT 0x0001 43 #define MDIO_MMD_PCS_MV_TEMP_SENSOR1_INT 0x0040 44 #define MDIO_MMD_PCS_MV_TEMP_SENSOR1_INT_EN 0x0080 45 46 #define MDIO_MMD_PCS_MV_TEMP_SENSOR2 32834 47 #define MDIO_MMD_PCS_MV_TEMP_SENSOR2_DIS_MASK 0xc000 48 49 #define MDIO_MMD_PCS_MV_TEMP_SENSOR3 32835 50 #define MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK 0xff00 51 #define MDIO_MMD_PCS_MV_TEMP_SENSOR3_MASK 0x00ff 52 53 #define MDIO_MMD_PCS_MV_100BT1_STAT1 33032 54 #define MDIO_MMD_PCS_MV_100BT1_STAT1_IDLE_ERROR 0x00ff 55 #define MDIO_MMD_PCS_MV_100BT1_STAT1_JABBER 0x0100 56 #define MDIO_MMD_PCS_MV_100BT1_STAT1_LINK 0x0200 57 #define MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_RX 0x1000 58 #define MDIO_MMD_PCS_MV_100BT1_STAT1_REMOTE_RX 0x2000 59 #define MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_MASTER 0x4000 60 61 #define MDIO_MMD_PCS_MV_100BT1_STAT2 33033 62 #define MDIO_MMD_PCS_MV_100BT1_STAT2_JABBER 0x0001 63 #define MDIO_MMD_PCS_MV_100BT1_STAT2_POL 0x0002 64 #define MDIO_MMD_PCS_MV_100BT1_STAT2_LINK 0x0004 65 #define MDIO_MMD_PCS_MV_100BT1_STAT2_ANGE 0x0008 66 67 #define MDIO_MMD_PCS_MV_100BT1_INT_EN 33042 68 #define MDIO_MMD_PCS_MV_100BT1_INT_EN_LINKEVENT 0x0400 69 70 #define MDIO_MMD_PCS_MV_COPPER_INT_STAT 33043 71 #define MDIO_MMD_PCS_MV_COPPER_INT_STAT_LINKEVENT 0x0400 72 73 #define MDIO_MMD_PCS_MV_RX_STAT 33328 74 75 #define MDIO_MMD_PCS_MV_TDR_RESET 65226 76 #define MDIO_MMD_PCS_MV_TDR_RESET_TDR_RST 0x1000 77 78 #define MDIO_MMD_PCS_MV_TDR_OFF_SHORT_CABLE 65241 79 80 #define MDIO_MMD_PCS_MV_TDR_OFF_LONG_CABLE 65242 81 82 #define MDIO_MMD_PCS_MV_TDR_STATUS 65245 83 #define MDIO_MMD_PCS_MV_TDR_STATUS_MASK 0x0003 84 #define MDIO_MMD_PCS_MV_TDR_STATUS_OFF 0x0001 85 #define MDIO_MMD_PCS_MV_TDR_STATUS_ON 0x0002 86 #define MDIO_MMD_PCS_MV_TDR_STATUS_DIST_MASK 0xff00 87 #define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_MASK 0x00f0 88 #define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_SHORT 0x0030 89 #define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OPEN 0x00e0 90 #define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OK 0x0070 91 #define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_IN_PROGR 0x0080 92 #define MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_NOISE 0x0050 93 94 #define MDIO_MMD_PCS_MV_TDR_OFF_CUTOFF 65246 95 96 struct mmd_val { 97 int devad; 98 u32 regnum; 99 u16 val; 100 }; 101 102 static const struct mmd_val mv88q222x_revb0_init_seq0[] = { 103 { MDIO_MMD_PCS, 0x8033, 0x6801 }, 104 { MDIO_MMD_AN, MDIO_AN_T1_CTRL, 0x0 }, 105 { MDIO_MMD_PMAPMD, MDIO_CTRL1, 106 MDIO_CTRL1_LPOWER | MDIO_PMA_CTRL1_SPEED1000 }, 107 { MDIO_MMD_PCS, 0xfe1b, 0x48 }, 108 { MDIO_MMD_PCS, 0xffe4, 0x6b6 }, 109 { MDIO_MMD_PMAPMD, MDIO_CTRL1, 0x0 }, 110 { MDIO_MMD_PCS, MDIO_CTRL1, 0x0 }, 111 }; 112 113 static const struct mmd_val mv88q222x_revb0_init_seq1[] = { 114 { MDIO_MMD_PCS, 0xfe79, 0x0 }, 115 { MDIO_MMD_PCS, 0xfe07, 0x125a }, 116 { MDIO_MMD_PCS, 0xfe09, 0x1288 }, 117 { MDIO_MMD_PCS, 0xfe08, 0x2588 }, 118 { MDIO_MMD_PCS, 0xfe11, 0x1105 }, 119 { MDIO_MMD_PCS, 0xfe72, 0x042c }, 120 { MDIO_MMD_PCS, 0xfbba, 0xcb2 }, 121 { MDIO_MMD_PCS, 0xfbbb, 0xc4a }, 122 { MDIO_MMD_AN, 0x8032, 0x2020 }, 123 { MDIO_MMD_AN, 0x8031, 0xa28 }, 124 { MDIO_MMD_AN, 0x8031, 0xc28 }, 125 { MDIO_MMD_PCS, 0xffdb, 0xfc10 }, 126 { MDIO_MMD_PCS, 0xfe1b, 0x58 }, 127 { MDIO_MMD_PCS, 0xfe79, 0x4 }, 128 { MDIO_MMD_PCS, 0xfe5f, 0xe8 }, 129 { MDIO_MMD_PCS, 0xfe05, 0x755c }, 130 }; 131 132 static int mv88q2xxx_soft_reset(struct phy_device *phydev) 133 { 134 int ret; 135 int val; 136 137 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 138 MDIO_PCS_1000BT1_CTRL, MDIO_PCS_1000BT1_CTRL_RESET); 139 if (ret < 0) 140 return ret; 141 142 return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS, 143 MDIO_PCS_1000BT1_CTRL, val, 144 !(val & MDIO_PCS_1000BT1_CTRL_RESET), 145 50000, 600000, true); 146 } 147 148 static int mv88q2xxx_read_link_gbit(struct phy_device *phydev) 149 { 150 int ret; 151 bool link = false; 152 153 /* Read vendor specific Auto-Negotiation status register to get local 154 * and remote receiver status according to software initialization 155 * guide. However, when not in polling mode the local and remote 156 * receiver status are not evaluated due to the Marvell 88Q2xxx APIs. 157 */ 158 ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT); 159 if (ret < 0) { 160 return ret; 161 } else if (((ret & MDIO_MMD_AN_MV_STAT_LOCAL_RX) && 162 (ret & MDIO_MMD_AN_MV_STAT_REMOTE_RX)) || 163 !phy_polling_mode(phydev)) { 164 /* The link state is latched low so that momentary link 165 * drops can be detected. Do not double-read the status 166 * in polling mode to detect such short link drops except 167 * the link was already down. 168 */ 169 if (!phy_polling_mode(phydev) || !phydev->link) { 170 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 171 MDIO_PCS_1000BT1_STAT); 172 if (ret < 0) 173 return ret; 174 else if (ret & MDIO_PCS_1000BT1_STAT_LINK) 175 link = true; 176 } 177 178 if (!link) { 179 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 180 MDIO_PCS_1000BT1_STAT); 181 if (ret < 0) 182 return ret; 183 else if (ret & MDIO_PCS_1000BT1_STAT_LINK) 184 link = true; 185 } 186 } 187 188 phydev->link = link; 189 190 return 0; 191 } 192 193 static int mv88q2xxx_read_link_100m(struct phy_device *phydev) 194 { 195 int ret; 196 197 /* The link state is latched low so that momentary link 198 * drops can be detected. Do not double-read the status 199 * in polling mode to detect such short link drops except 200 * the link was already down. In case we are not polling, 201 * we always read the realtime status. 202 */ 203 if (!phy_polling_mode(phydev)) { 204 phydev->link = false; 205 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 206 MDIO_MMD_PCS_MV_100BT1_STAT2); 207 if (ret < 0) 208 return ret; 209 210 if (ret & MDIO_MMD_PCS_MV_100BT1_STAT2_LINK) 211 phydev->link = true; 212 213 return 0; 214 } else if (!phydev->link) { 215 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 216 MDIO_MMD_PCS_MV_100BT1_STAT1); 217 if (ret < 0) 218 return ret; 219 else if (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LINK) 220 goto out; 221 } 222 223 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_100BT1_STAT1); 224 if (ret < 0) 225 return ret; 226 227 out: 228 /* Check if we have link and if the remote and local receiver are ok */ 229 if ((ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LINK) && 230 (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_LOCAL_RX) && 231 (ret & MDIO_MMD_PCS_MV_100BT1_STAT1_REMOTE_RX)) 232 phydev->link = true; 233 else 234 phydev->link = false; 235 236 return 0; 237 } 238 239 static int mv88q2xxx_read_link(struct phy_device *phydev) 240 { 241 /* The 88Q2XXX PHYs do not have the PMA/PMD status register available, 242 * therefore we need to read the link status from the vendor specific 243 * registers depending on the speed. 244 */ 245 246 if (phydev->speed == SPEED_1000) 247 return mv88q2xxx_read_link_gbit(phydev); 248 else if (phydev->speed == SPEED_100) 249 return mv88q2xxx_read_link_100m(phydev); 250 251 phydev->link = false; 252 return 0; 253 } 254 255 static int mv88q2xxx_read_master_slave_state(struct phy_device *phydev) 256 { 257 int ret; 258 259 phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; 260 ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT); 261 if (ret < 0) 262 return ret; 263 264 if (ret & MDIO_MMD_AN_MV_STAT_LOCAL_MASTER) 265 phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; 266 else 267 phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; 268 269 return 0; 270 } 271 272 static int mv88q2xxx_read_aneg_speed(struct phy_device *phydev) 273 { 274 int ret; 275 276 phydev->speed = SPEED_UNKNOWN; 277 ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT2); 278 if (ret < 0) 279 return ret; 280 281 if (!(ret & MDIO_MMD_AN_MV_STAT2_AN_RESOLVED)) 282 return 0; 283 284 if (ret & MDIO_MMD_AN_MV_STAT2_100BT1) 285 phydev->speed = SPEED_100; 286 else if (ret & MDIO_MMD_AN_MV_STAT2_1000BT1) 287 phydev->speed = SPEED_1000; 288 289 return 0; 290 } 291 292 static int mv88q2xxx_read_status(struct phy_device *phydev) 293 { 294 int ret; 295 296 if (phydev->autoneg == AUTONEG_ENABLE) { 297 /* We have to get the negotiated speed first, otherwise we are 298 * not able to read the link. 299 */ 300 ret = mv88q2xxx_read_aneg_speed(phydev); 301 if (ret < 0) 302 return ret; 303 304 ret = mv88q2xxx_read_link(phydev); 305 if (ret < 0) 306 return ret; 307 308 ret = genphy_c45_read_lpa(phydev); 309 if (ret < 0) 310 return ret; 311 312 ret = genphy_c45_baset1_read_status(phydev); 313 if (ret < 0) 314 return ret; 315 316 ret = mv88q2xxx_read_master_slave_state(phydev); 317 if (ret < 0) 318 return ret; 319 320 phy_resolve_aneg_linkmode(phydev); 321 322 return 0; 323 } 324 325 ret = mv88q2xxx_read_link(phydev); 326 if (ret < 0) 327 return ret; 328 329 return genphy_c45_read_pma(phydev); 330 } 331 332 static int mv88q2xxx_get_features(struct phy_device *phydev) 333 { 334 int ret; 335 336 ret = genphy_c45_pma_read_abilities(phydev); 337 if (ret) 338 return ret; 339 340 /* We need to read the baset1 extended abilities manually because the 341 * PHY does not signalize it has the extended abilities register 342 * available. 343 */ 344 ret = genphy_c45_pma_baset1_read_abilities(phydev); 345 if (ret) 346 return ret; 347 348 /* The PHY signalizes it supports autonegotiation. Unfortunately, so 349 * far it was not possible to get a link even when following the init 350 * sequence provided by Marvell. Disable it for now until a proper 351 * workaround is found or a new PHY revision is released. 352 */ 353 if (phydev->drv->phy_id == MARVELL_PHY_ID_88Q2110) 354 linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, 355 phydev->supported); 356 357 return 0; 358 } 359 360 static int mv88q2xxx_config_aneg(struct phy_device *phydev) 361 { 362 int ret; 363 364 ret = genphy_c45_config_aneg(phydev); 365 if (ret) 366 return ret; 367 368 return phydev->drv->soft_reset(phydev); 369 } 370 371 static int mv88q2xxx_config_init(struct phy_device *phydev) 372 { 373 /* The 88Q2XXX PHYs do have the extended ability register available, but 374 * register MDIO_PMA_EXTABLE where they should signalize it does not 375 * work according to specification. Therefore, we force it here. 376 */ 377 phydev->pma_extable = MDIO_PMA_EXTABLE_BT1; 378 379 /* Configure interrupt with default settings, output is driven low for 380 * active interrupt and high for inactive. 381 */ 382 if (phy_interrupt_is_valid(phydev)) 383 return phy_set_bits_mmd(phydev, MDIO_MMD_PCS, 384 MDIO_MMD_PCS_MV_GPIO_INT_CTRL, 385 MDIO_MMD_PCS_MV_GPIO_INT_CTRL_TRI_DIS); 386 387 return 0; 388 } 389 390 static int mv88q2xxx_get_sqi(struct phy_device *phydev) 391 { 392 int ret; 393 394 if (phydev->speed == SPEED_100) { 395 /* Read the SQI from the vendor specific receiver status 396 * register 397 */ 398 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 399 MDIO_MMD_PCS_MV_RX_STAT); 400 if (ret < 0) 401 return ret; 402 403 ret = ret >> 12; 404 } else { 405 /* Read from vendor specific registers, they are not documented 406 * but can be found in the Software Initialization Guide. Only 407 * revisions >= A0 are supported. 408 */ 409 ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, 0xfc5d, 0xff, 0xac); 410 if (ret < 0) 411 return ret; 412 413 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 0xfc88); 414 if (ret < 0) 415 return ret; 416 } 417 418 return ret & 0x0f; 419 } 420 421 static int mv88q2xxx_get_sqi_max(struct phy_device *phydev) 422 { 423 return 15; 424 } 425 426 static int mv88q2xxx_config_intr(struct phy_device *phydev) 427 { 428 int ret; 429 430 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 431 /* Enable interrupts for 1000BASE-T1 link up and down events 432 * and enable general interrupts for 100BASE-T1. 433 */ 434 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 435 MDIO_MMD_PCS_MV_INT_EN, 436 MDIO_MMD_PCS_MV_INT_EN_LINK_UP | 437 MDIO_MMD_PCS_MV_INT_EN_LINK_DOWN | 438 MDIO_MMD_PCS_MV_INT_EN_100BT1); 439 if (ret < 0) 440 return ret; 441 442 /* Enable interrupts for 100BASE-T1 link events */ 443 return phy_write_mmd(phydev, MDIO_MMD_PCS, 444 MDIO_MMD_PCS_MV_100BT1_INT_EN, 445 MDIO_MMD_PCS_MV_100BT1_INT_EN_LINKEVENT); 446 } else { 447 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 448 MDIO_MMD_PCS_MV_INT_EN, 0); 449 if (ret < 0) 450 return ret; 451 452 return phy_write_mmd(phydev, MDIO_MMD_PCS, 453 MDIO_MMD_PCS_MV_100BT1_INT_EN, 0); 454 } 455 } 456 457 static irqreturn_t mv88q2xxx_handle_interrupt(struct phy_device *phydev) 458 { 459 bool trigger_machine = false; 460 int irq; 461 462 /* Before we can acknowledge the 100BT1 general interrupt, that is in 463 * the 1000BT1 interrupt status register, we have to acknowledge any 464 * interrupts that are related to it. Therefore we read first the 100BT1 465 * interrupt status register, followed by reading the 1000BT1 interrupt 466 * status register. 467 */ 468 469 irq = phy_read_mmd(phydev, MDIO_MMD_PCS, 470 MDIO_MMD_PCS_MV_COPPER_INT_STAT); 471 if (irq < 0) { 472 phy_error(phydev); 473 return IRQ_NONE; 474 } 475 476 /* Check link status for 100BT1 */ 477 if (irq & MDIO_MMD_PCS_MV_COPPER_INT_STAT_LINKEVENT) 478 trigger_machine = true; 479 480 irq = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_GPIO_INT_STAT); 481 if (irq < 0) { 482 phy_error(phydev); 483 return IRQ_NONE; 484 } 485 486 /* Check link status for 1000BT1 */ 487 if ((irq & MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_UP) || 488 (irq & MDIO_MMD_PCS_MV_GPIO_INT_STAT_LINK_DOWN)) 489 trigger_machine = true; 490 491 if (!trigger_machine) 492 return IRQ_NONE; 493 494 phy_trigger_machine(phydev); 495 496 return IRQ_HANDLED; 497 } 498 499 static int mv88q2xxx_suspend(struct phy_device *phydev) 500 { 501 int ret; 502 503 /* Disable PHY interrupts */ 504 if (phy_interrupt_is_valid(phydev)) { 505 phydev->interrupts = PHY_INTERRUPT_DISABLED; 506 ret = mv88q2xxx_config_intr(phydev); 507 if (ret) 508 return ret; 509 } 510 511 return phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, 512 MDIO_CTRL1_LPOWER); 513 } 514 515 static int mv88q2xxx_resume(struct phy_device *phydev) 516 { 517 int ret; 518 519 /* Enable PHY interrupts */ 520 if (phy_interrupt_is_valid(phydev)) { 521 phydev->interrupts = PHY_INTERRUPT_ENABLED; 522 ret = mv88q2xxx_config_intr(phydev); 523 if (ret) 524 return ret; 525 } 526 527 return phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, 528 MDIO_CTRL1_LPOWER); 529 } 530 531 #if IS_ENABLED(CONFIG_HWMON) 532 static const struct hwmon_channel_info * const mv88q2xxx_hwmon_info[] = { 533 HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_ALARM), 534 NULL 535 }; 536 537 static umode_t mv88q2xxx_hwmon_is_visible(const void *data, 538 enum hwmon_sensor_types type, 539 u32 attr, int channel) 540 { 541 switch (attr) { 542 case hwmon_temp_input: 543 return 0444; 544 case hwmon_temp_max: 545 return 0644; 546 case hwmon_temp_alarm: 547 return 0444; 548 default: 549 return 0; 550 } 551 } 552 553 static int mv88q2xxx_hwmon_read(struct device *dev, 554 enum hwmon_sensor_types type, 555 u32 attr, int channel, long *val) 556 { 557 struct phy_device *phydev = dev_get_drvdata(dev); 558 int ret; 559 560 switch (attr) { 561 case hwmon_temp_input: 562 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 563 MDIO_MMD_PCS_MV_TEMP_SENSOR3); 564 if (ret < 0) 565 return ret; 566 567 ret = FIELD_GET(MDIO_MMD_PCS_MV_TEMP_SENSOR3_MASK, ret); 568 *val = (ret - 75) * 1000; 569 return 0; 570 case hwmon_temp_max: 571 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 572 MDIO_MMD_PCS_MV_TEMP_SENSOR3); 573 if (ret < 0) 574 return ret; 575 576 ret = FIELD_GET(MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK, 577 ret); 578 *val = (ret - 75) * 1000; 579 return 0; 580 case hwmon_temp_alarm: 581 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, 582 MDIO_MMD_PCS_MV_TEMP_SENSOR1); 583 if (ret < 0) 584 return ret; 585 586 *val = !!(ret & MDIO_MMD_PCS_MV_TEMP_SENSOR1_RAW_INT); 587 return 0; 588 default: 589 return -EOPNOTSUPP; 590 } 591 } 592 593 static int mv88q2xxx_hwmon_write(struct device *dev, 594 enum hwmon_sensor_types type, u32 attr, 595 int channel, long val) 596 { 597 struct phy_device *phydev = dev_get_drvdata(dev); 598 599 switch (attr) { 600 case hwmon_temp_max: 601 clamp_val(val, -75000, 180000); 602 val = (val / 1000) + 75; 603 val = FIELD_PREP(MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK, 604 val); 605 return phy_modify_mmd(phydev, MDIO_MMD_PCS, 606 MDIO_MMD_PCS_MV_TEMP_SENSOR3, 607 MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK, 608 val); 609 default: 610 return -EOPNOTSUPP; 611 } 612 } 613 614 static const struct hwmon_ops mv88q2xxx_hwmon_hwmon_ops = { 615 .is_visible = mv88q2xxx_hwmon_is_visible, 616 .read = mv88q2xxx_hwmon_read, 617 .write = mv88q2xxx_hwmon_write, 618 }; 619 620 static const struct hwmon_chip_info mv88q2xxx_hwmon_chip_info = { 621 .ops = &mv88q2xxx_hwmon_hwmon_ops, 622 .info = mv88q2xxx_hwmon_info, 623 }; 624 625 static int mv88q2xxx_hwmon_probe(struct phy_device *phydev) 626 { 627 struct device *dev = &phydev->mdio.dev; 628 struct device *hwmon; 629 char *hwmon_name; 630 int ret; 631 632 /* Enable temperature sense */ 633 ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TEMP_SENSOR2, 634 MDIO_MMD_PCS_MV_TEMP_SENSOR2_DIS_MASK, 0); 635 if (ret < 0) 636 return ret; 637 638 hwmon_name = devm_hwmon_sanitize_name(dev, dev_name(dev)); 639 if (IS_ERR(hwmon_name)) 640 return PTR_ERR(hwmon_name); 641 642 hwmon = devm_hwmon_device_register_with_info(dev, 643 hwmon_name, 644 phydev, 645 &mv88q2xxx_hwmon_chip_info, 646 NULL); 647 648 return PTR_ERR_OR_ZERO(hwmon); 649 } 650 651 #else 652 static int mv88q2xxx_hwmon_probe(struct phy_device *phydev) 653 { 654 return 0; 655 } 656 #endif 657 658 static int mv88q2xxx_probe(struct phy_device *phydev) 659 { 660 return mv88q2xxx_hwmon_probe(phydev); 661 } 662 663 static int mv88q222x_soft_reset(struct phy_device *phydev) 664 { 665 int ret; 666 667 /* Enable RESET of DCL */ 668 if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed == SPEED_1000) { 669 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 0xfe1b, 0x48); 670 if (ret < 0) 671 return ret; 672 } 673 674 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_1000BT1_CTRL, 675 MDIO_PCS_1000BT1_CTRL_RESET); 676 if (ret < 0) 677 return ret; 678 679 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 0xffe4, 0xc); 680 if (ret < 0) 681 return ret; 682 683 /* Disable RESET of DCL */ 684 if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed == SPEED_1000) 685 return phy_write_mmd(phydev, MDIO_MMD_PCS, 0xfe1b, 0x58); 686 687 return 0; 688 } 689 690 static int mv88q222x_revb0_config_init(struct phy_device *phydev) 691 { 692 int ret, i; 693 694 for (i = 0; i < ARRAY_SIZE(mv88q222x_revb0_init_seq0); i++) { 695 ret = phy_write_mmd(phydev, mv88q222x_revb0_init_seq0[i].devad, 696 mv88q222x_revb0_init_seq0[i].regnum, 697 mv88q222x_revb0_init_seq0[i].val); 698 if (ret < 0) 699 return ret; 700 } 701 702 usleep_range(5000, 10000); 703 704 for (i = 0; i < ARRAY_SIZE(mv88q222x_revb0_init_seq1); i++) { 705 ret = phy_write_mmd(phydev, mv88q222x_revb0_init_seq1[i].devad, 706 mv88q222x_revb0_init_seq1[i].regnum, 707 mv88q222x_revb0_init_seq1[i].val); 708 if (ret < 0) 709 return ret; 710 } 711 712 return mv88q2xxx_config_init(phydev); 713 } 714 715 static int mv88q222x_cable_test_start(struct phy_device *phydev) 716 { 717 int ret; 718 719 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 720 MDIO_MMD_PCS_MV_TDR_OFF_CUTOFF, 0x0058); 721 if (ret < 0) 722 return ret; 723 724 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 725 MDIO_MMD_PCS_MV_TDR_OFF_LONG_CABLE, 0x00eb); 726 if (ret < 0) 727 return ret; 728 729 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, 730 MDIO_MMD_PCS_MV_TDR_OFF_SHORT_CABLE, 0x010e); 731 if (ret < 0) 732 return ret; 733 734 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_RESET, 735 0x0d90); 736 if (ret < 0) 737 return ret; 738 739 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_STATUS, 740 MDIO_MMD_PCS_MV_TDR_STATUS_ON); 741 if (ret < 0) 742 return ret; 743 744 /* According to the Marvell API the test is finished within 500 ms */ 745 msleep(500); 746 747 return 0; 748 } 749 750 static int mv88q222x_cable_test_get_status(struct phy_device *phydev, 751 bool *finished) 752 { 753 int ret, status; 754 u32 dist; 755 756 status = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_STATUS); 757 if (status < 0) 758 return status; 759 760 ret = phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_MMD_PCS_MV_TDR_RESET, 761 MDIO_MMD_PCS_MV_TDR_RESET_TDR_RST | 0xd90); 762 if (ret < 0) 763 return ret; 764 765 /* Test could not be finished */ 766 if (FIELD_GET(MDIO_MMD_PCS_MV_TDR_STATUS_MASK, status) != 767 MDIO_MMD_PCS_MV_TDR_STATUS_OFF) 768 return -ETIMEDOUT; 769 770 *finished = true; 771 /* Fault length reported in meters, convert to centimeters */ 772 dist = FIELD_GET(MDIO_MMD_PCS_MV_TDR_STATUS_DIST_MASK, status) * 100; 773 switch (status & MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_MASK) { 774 case MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OPEN: 775 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 776 ETHTOOL_A_CABLE_RESULT_CODE_OPEN); 777 ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, 778 dist); 779 break; 780 case MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_SHORT: 781 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 782 ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT); 783 ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, 784 dist); 785 break; 786 case MDIO_MMD_PCS_MV_TDR_STATUS_VCT_STAT_OK: 787 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 788 ETHTOOL_A_CABLE_RESULT_CODE_OK); 789 break; 790 default: 791 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 792 ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC); 793 } 794 795 return 0; 796 } 797 798 static struct phy_driver mv88q2xxx_driver[] = { 799 { 800 .phy_id = MARVELL_PHY_ID_88Q2110, 801 .phy_id_mask = MARVELL_PHY_ID_MASK, 802 .name = "mv88q2110", 803 .get_features = mv88q2xxx_get_features, 804 .config_aneg = mv88q2xxx_config_aneg, 805 .config_init = mv88q2xxx_config_init, 806 .read_status = mv88q2xxx_read_status, 807 .soft_reset = mv88q2xxx_soft_reset, 808 .set_loopback = genphy_c45_loopback, 809 .get_sqi = mv88q2xxx_get_sqi, 810 .get_sqi_max = mv88q2xxx_get_sqi_max, 811 }, 812 { 813 PHY_ID_MATCH_EXACT(PHY_ID_88Q2220_REVB0), 814 .name = "mv88q2220", 815 .flags = PHY_POLL_CABLE_TEST, 816 .probe = mv88q2xxx_probe, 817 .get_features = mv88q2xxx_get_features, 818 .config_aneg = mv88q2xxx_config_aneg, 819 .aneg_done = genphy_c45_aneg_done, 820 .config_init = mv88q222x_revb0_config_init, 821 .read_status = mv88q2xxx_read_status, 822 .soft_reset = mv88q222x_soft_reset, 823 .config_intr = mv88q2xxx_config_intr, 824 .handle_interrupt = mv88q2xxx_handle_interrupt, 825 .set_loopback = genphy_c45_loopback, 826 .cable_test_start = mv88q222x_cable_test_start, 827 .cable_test_get_status = mv88q222x_cable_test_get_status, 828 .get_sqi = mv88q2xxx_get_sqi, 829 .get_sqi_max = mv88q2xxx_get_sqi_max, 830 .suspend = mv88q2xxx_suspend, 831 .resume = mv88q2xxx_resume, 832 }, 833 }; 834 835 module_phy_driver(mv88q2xxx_driver); 836 837 static struct mdio_device_id __maybe_unused mv88q2xxx_tbl[] = { 838 { MARVELL_PHY_ID_88Q2110, MARVELL_PHY_ID_MASK }, 839 { PHY_ID_MATCH_EXACT(PHY_ID_88Q2220_REVB0), }, 840 { /*sentinel*/ } 841 }; 842 MODULE_DEVICE_TABLE(mdio, mv88q2xxx_tbl); 843 844 MODULE_DESCRIPTION("Marvell 88Q2XXX 100/1000BASE-T1 Automotive Ethernet PHY driver"); 845 MODULE_LICENSE("GPL"); 846