1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (C) 2018 Microchip Technology 3 4 #include <linux/kernel.h> 5 #include <linux/module.h> 6 #include <linux/delay.h> 7 #include <linux/mii.h> 8 #include <linux/phy.h> 9 #include <linux/ethtool.h> 10 #include <linux/ethtool_netlink.h> 11 12 /* External Register Control Register */ 13 #define LAN87XX_EXT_REG_CTL (0x14) 14 #define LAN87XX_EXT_REG_CTL_RD_CTL (0x1000) 15 #define LAN87XX_EXT_REG_CTL_WR_CTL (0x0800) 16 17 /* External Register Read Data Register */ 18 #define LAN87XX_EXT_REG_RD_DATA (0x15) 19 20 /* External Register Write Data Register */ 21 #define LAN87XX_EXT_REG_WR_DATA (0x16) 22 23 /* Interrupt Source Register */ 24 #define LAN87XX_INTERRUPT_SOURCE (0x18) 25 26 /* Interrupt Mask Register */ 27 #define LAN87XX_INTERRUPT_MASK (0x19) 28 #define LAN87XX_MASK_LINK_UP (0x0004) 29 #define LAN87XX_MASK_LINK_DOWN (0x0002) 30 31 /* MISC Control 1 Register */ 32 #define LAN87XX_CTRL_1 (0x11) 33 #define LAN87XX_MASK_RGMII_TXC_DLY_EN (0x4000) 34 #define LAN87XX_MASK_RGMII_RXC_DLY_EN (0x2000) 35 36 /* phyaccess nested types */ 37 #define PHYACC_ATTR_MODE_READ 0 38 #define PHYACC_ATTR_MODE_WRITE 1 39 #define PHYACC_ATTR_MODE_MODIFY 2 40 41 #define PHYACC_ATTR_BANK_SMI 0 42 #define PHYACC_ATTR_BANK_MISC 1 43 #define PHYACC_ATTR_BANK_PCS 2 44 #define PHYACC_ATTR_BANK_AFE 3 45 #define PHYACC_ATTR_BANK_DSP 4 46 #define PHYACC_ATTR_BANK_MAX 7 47 48 /* measurement defines */ 49 #define LAN87XX_CABLE_TEST_OK 0 50 #define LAN87XX_CABLE_TEST_OPEN 1 51 #define LAN87XX_CABLE_TEST_SAME_SHORT 2 52 53 #define DRIVER_AUTHOR "Nisar Sayed <nisar.sayed@microchip.com>" 54 #define DRIVER_DESC "Microchip LAN87XX T1 PHY driver" 55 56 struct access_ereg_val { 57 u8 mode; 58 u8 bank; 59 u8 offset; 60 u16 val; 61 u16 mask; 62 }; 63 64 static int access_ereg(struct phy_device *phydev, u8 mode, u8 bank, 65 u8 offset, u16 val) 66 { 67 u16 ereg = 0; 68 int rc = 0; 69 70 if (mode > PHYACC_ATTR_MODE_WRITE || bank > PHYACC_ATTR_BANK_MAX) 71 return -EINVAL; 72 73 if (bank == PHYACC_ATTR_BANK_SMI) { 74 if (mode == PHYACC_ATTR_MODE_WRITE) 75 rc = phy_write(phydev, offset, val); 76 else 77 rc = phy_read(phydev, offset); 78 return rc; 79 } 80 81 if (mode == PHYACC_ATTR_MODE_WRITE) { 82 ereg = LAN87XX_EXT_REG_CTL_WR_CTL; 83 rc = phy_write(phydev, LAN87XX_EXT_REG_WR_DATA, val); 84 if (rc < 0) 85 return rc; 86 } else { 87 ereg = LAN87XX_EXT_REG_CTL_RD_CTL; 88 } 89 90 ereg |= (bank << 8) | offset; 91 92 rc = phy_write(phydev, LAN87XX_EXT_REG_CTL, ereg); 93 if (rc < 0) 94 return rc; 95 96 if (mode == PHYACC_ATTR_MODE_READ) 97 rc = phy_read(phydev, LAN87XX_EXT_REG_RD_DATA); 98 99 return rc; 100 } 101 102 static int access_ereg_modify_changed(struct phy_device *phydev, 103 u8 bank, u8 offset, u16 val, u16 mask) 104 { 105 int new = 0, rc = 0; 106 107 if (bank > PHYACC_ATTR_BANK_MAX) 108 return -EINVAL; 109 110 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, bank, offset, val); 111 if (rc < 0) 112 return rc; 113 114 new = val | (rc & (mask ^ 0xFFFF)); 115 rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE, bank, offset, new); 116 117 return rc; 118 } 119 120 static int lan87xx_config_rgmii_delay(struct phy_device *phydev) 121 { 122 int rc; 123 124 if (!phy_interface_is_rgmii(phydev)) 125 return 0; 126 127 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 128 PHYACC_ATTR_BANK_MISC, LAN87XX_CTRL_1, 0); 129 if (rc < 0) 130 return rc; 131 132 switch (phydev->interface) { 133 case PHY_INTERFACE_MODE_RGMII: 134 rc &= ~LAN87XX_MASK_RGMII_TXC_DLY_EN; 135 rc &= ~LAN87XX_MASK_RGMII_RXC_DLY_EN; 136 break; 137 case PHY_INTERFACE_MODE_RGMII_ID: 138 rc |= LAN87XX_MASK_RGMII_TXC_DLY_EN; 139 rc |= LAN87XX_MASK_RGMII_RXC_DLY_EN; 140 break; 141 case PHY_INTERFACE_MODE_RGMII_RXID: 142 rc &= ~LAN87XX_MASK_RGMII_TXC_DLY_EN; 143 rc |= LAN87XX_MASK_RGMII_RXC_DLY_EN; 144 break; 145 case PHY_INTERFACE_MODE_RGMII_TXID: 146 rc |= LAN87XX_MASK_RGMII_TXC_DLY_EN; 147 rc &= ~LAN87XX_MASK_RGMII_RXC_DLY_EN; 148 break; 149 default: 150 return 0; 151 } 152 153 return access_ereg(phydev, PHYACC_ATTR_MODE_WRITE, 154 PHYACC_ATTR_BANK_MISC, LAN87XX_CTRL_1, rc); 155 } 156 157 static int lan87xx_phy_init(struct phy_device *phydev) 158 { 159 static const struct access_ereg_val init[] = { 160 /* TX Amplitude = 5 */ 161 {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_AFE, 0x0B, 162 0x000A, 0x001E}, 163 /* Clear SMI interrupts */ 164 {PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI, 0x18, 165 0, 0}, 166 /* Clear MISC interrupts */ 167 {PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_MISC, 0x08, 168 0, 0}, 169 /* Turn on TC10 Ring Oscillator (ROSC) */ 170 {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_MISC, 0x20, 171 0x0020, 0x0020}, 172 /* WUR Detect Length to 1.2uS, LPC Detect Length to 1.09uS */ 173 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_PCS, 0x20, 174 0x283C, 0}, 175 /* Wake_In Debounce Length to 39uS, Wake_Out Length to 79uS */ 176 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_MISC, 0x21, 177 0x274F, 0}, 178 /* Enable Auto Wake Forward to Wake_Out, ROSC on, Sleep, 179 * and Wake_In to wake PHY 180 */ 181 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_MISC, 0x20, 182 0x80A7, 0}, 183 /* Enable WUP Auto Fwd, Enable Wake on MDI, Wakeup Debouncer 184 * to 128 uS 185 */ 186 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_MISC, 0x24, 187 0xF110, 0}, 188 /* Enable HW Init */ 189 {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_SMI, 0x1A, 190 0x0100, 0x0100}, 191 }; 192 int rc, i; 193 194 /* Start manual initialization procedures in Managed Mode */ 195 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI, 196 0x1a, 0x0000, 0x0100); 197 if (rc < 0) 198 return rc; 199 200 /* Soft Reset the SMI block */ 201 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI, 202 0x00, 0x8000, 0x8000); 203 if (rc < 0) 204 return rc; 205 206 /* Check to see if the self-clearing bit is cleared */ 207 usleep_range(1000, 2000); 208 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 209 PHYACC_ATTR_BANK_SMI, 0x00, 0); 210 if (rc < 0) 211 return rc; 212 if ((rc & 0x8000) != 0) 213 return -ETIMEDOUT; 214 215 /* PHY Initialization */ 216 for (i = 0; i < ARRAY_SIZE(init); i++) { 217 if (init[i].mode == PHYACC_ATTR_MODE_MODIFY) { 218 rc = access_ereg_modify_changed(phydev, init[i].bank, 219 init[i].offset, 220 init[i].val, 221 init[i].mask); 222 } else { 223 rc = access_ereg(phydev, init[i].mode, init[i].bank, 224 init[i].offset, init[i].val); 225 } 226 if (rc < 0) 227 return rc; 228 } 229 230 return lan87xx_config_rgmii_delay(phydev); 231 } 232 233 static int lan87xx_phy_config_intr(struct phy_device *phydev) 234 { 235 int rc, val = 0; 236 237 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 238 /* unmask all source and clear them before enable */ 239 rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, 0x7FFF); 240 rc = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE); 241 val = LAN87XX_MASK_LINK_UP | LAN87XX_MASK_LINK_DOWN; 242 rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, val); 243 } else { 244 rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, val); 245 if (rc) 246 return rc; 247 248 rc = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE); 249 } 250 251 return rc < 0 ? rc : 0; 252 } 253 254 static irqreturn_t lan87xx_handle_interrupt(struct phy_device *phydev) 255 { 256 int irq_status; 257 258 irq_status = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE); 259 if (irq_status < 0) { 260 phy_error(phydev); 261 return IRQ_NONE; 262 } 263 264 if (irq_status == 0) 265 return IRQ_NONE; 266 267 phy_trigger_machine(phydev); 268 269 return IRQ_HANDLED; 270 } 271 272 static int lan87xx_config_init(struct phy_device *phydev) 273 { 274 int rc = lan87xx_phy_init(phydev); 275 276 return rc < 0 ? rc : 0; 277 } 278 279 static int microchip_cable_test_start_common(struct phy_device *phydev) 280 { 281 int bmcr, bmsr, ret; 282 283 /* If auto-negotiation is enabled, but not complete, the cable 284 * test never completes. So disable auto-neg. 285 */ 286 bmcr = phy_read(phydev, MII_BMCR); 287 if (bmcr < 0) 288 return bmcr; 289 290 bmsr = phy_read(phydev, MII_BMSR); 291 292 if (bmsr < 0) 293 return bmsr; 294 295 if (bmcr & BMCR_ANENABLE) { 296 ret = phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0); 297 if (ret < 0) 298 return ret; 299 ret = genphy_soft_reset(phydev); 300 if (ret < 0) 301 return ret; 302 } 303 304 /* If the link is up, allow it some time to go down */ 305 if (bmsr & BMSR_LSTATUS) 306 msleep(1500); 307 308 return 0; 309 } 310 311 static int lan87xx_cable_test_start(struct phy_device *phydev) 312 { 313 static const struct access_ereg_val cable_test[] = { 314 /* min wait */ 315 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 93, 316 0, 0}, 317 /* max wait */ 318 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 94, 319 10, 0}, 320 /* pulse cycle */ 321 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 95, 322 90, 0}, 323 /* cable diag thresh */ 324 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 92, 325 60, 0}, 326 /* max gain */ 327 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 79, 328 31, 0}, 329 /* clock align for each iteration */ 330 {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_DSP, 55, 331 0, 0x0038}, 332 /* max cycle wait config */ 333 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 94, 334 70, 0}, 335 /* start cable diag*/ 336 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 90, 337 1, 0}, 338 }; 339 int rc, i; 340 341 rc = microchip_cable_test_start_common(phydev); 342 if (rc < 0) 343 return rc; 344 345 /* start cable diag */ 346 /* check if part is alive - if not, return diagnostic error */ 347 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI, 348 0x00, 0); 349 if (rc < 0) 350 return rc; 351 352 /* master/slave specific configs */ 353 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI, 354 0x0A, 0); 355 if (rc < 0) 356 return rc; 357 358 if ((rc & 0x4000) != 0x4000) { 359 /* DUT is Slave */ 360 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_AFE, 361 0x0E, 0x5, 0x7); 362 if (rc < 0) 363 return rc; 364 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI, 365 0x1A, 0x8, 0x8); 366 if (rc < 0) 367 return rc; 368 } else { 369 /* DUT is Master */ 370 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI, 371 0x10, 0x8, 0x40); 372 if (rc < 0) 373 return rc; 374 } 375 376 for (i = 0; i < ARRAY_SIZE(cable_test); i++) { 377 if (cable_test[i].mode == PHYACC_ATTR_MODE_MODIFY) { 378 rc = access_ereg_modify_changed(phydev, 379 cable_test[i].bank, 380 cable_test[i].offset, 381 cable_test[i].val, 382 cable_test[i].mask); 383 /* wait 50ms */ 384 msleep(50); 385 } else { 386 rc = access_ereg(phydev, cable_test[i].mode, 387 cable_test[i].bank, 388 cable_test[i].offset, 389 cable_test[i].val); 390 } 391 if (rc < 0) 392 return rc; 393 } 394 /* cable diag started */ 395 396 return 0; 397 } 398 399 static int lan87xx_cable_test_report_trans(u32 result) 400 { 401 switch (result) { 402 case LAN87XX_CABLE_TEST_OK: 403 return ETHTOOL_A_CABLE_RESULT_CODE_OK; 404 case LAN87XX_CABLE_TEST_OPEN: 405 return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; 406 case LAN87XX_CABLE_TEST_SAME_SHORT: 407 return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; 408 default: 409 /* DIAGNOSTIC_ERROR */ 410 return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; 411 } 412 } 413 414 static int lan87xx_cable_test_report(struct phy_device *phydev) 415 { 416 int pos_peak_cycle = 0, pos_peak_in_phases = 0, pos_peak_phase = 0; 417 int neg_peak_cycle = 0, neg_peak_in_phases = 0, neg_peak_phase = 0; 418 int noise_margin = 20, time_margin = 89, jitter_var = 30; 419 int min_time_diff = 96, max_time_diff = 96 + time_margin; 420 bool fault = false, check_a = false, check_b = false; 421 int gain_idx = 0, pos_peak = 0, neg_peak = 0; 422 int pos_peak_time = 0, neg_peak_time = 0; 423 int pos_peak_in_phases_hybrid = 0; 424 int detect = -1; 425 426 gain_idx = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 427 PHYACC_ATTR_BANK_DSP, 151, 0); 428 /* read non-hybrid results */ 429 pos_peak = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 430 PHYACC_ATTR_BANK_DSP, 153, 0); 431 neg_peak = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 432 PHYACC_ATTR_BANK_DSP, 154, 0); 433 pos_peak_time = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 434 PHYACC_ATTR_BANK_DSP, 156, 0); 435 neg_peak_time = access_ereg(phydev, PHYACC_ATTR_MODE_READ, 436 PHYACC_ATTR_BANK_DSP, 157, 0); 437 438 pos_peak_cycle = (pos_peak_time >> 7) & 0x7F; 439 /* calculate non-hybrid values */ 440 pos_peak_phase = pos_peak_time & 0x7F; 441 pos_peak_in_phases = (pos_peak_cycle * 96) + pos_peak_phase; 442 neg_peak_cycle = (neg_peak_time >> 7) & 0x7F; 443 neg_peak_phase = neg_peak_time & 0x7F; 444 neg_peak_in_phases = (neg_peak_cycle * 96) + neg_peak_phase; 445 446 /* process values */ 447 check_a = 448 ((pos_peak_in_phases - neg_peak_in_phases) >= min_time_diff) && 449 ((pos_peak_in_phases - neg_peak_in_phases) < max_time_diff) && 450 pos_peak_in_phases_hybrid < pos_peak_in_phases && 451 (pos_peak_in_phases_hybrid < (neg_peak_in_phases + jitter_var)); 452 check_b = 453 ((neg_peak_in_phases - pos_peak_in_phases) >= min_time_diff) && 454 ((neg_peak_in_phases - pos_peak_in_phases) < max_time_diff) && 455 pos_peak_in_phases_hybrid < neg_peak_in_phases && 456 (pos_peak_in_phases_hybrid < (pos_peak_in_phases + jitter_var)); 457 458 if (pos_peak_in_phases > neg_peak_in_phases && check_a) 459 detect = 2; 460 else if ((neg_peak_in_phases > pos_peak_in_phases) && check_b) 461 detect = 1; 462 463 if (pos_peak > noise_margin && neg_peak > noise_margin && 464 gain_idx >= 0) { 465 if (detect == 1 || detect == 2) 466 fault = true; 467 } 468 469 if (!fault) 470 detect = 0; 471 472 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 473 lan87xx_cable_test_report_trans(detect)); 474 475 return 0; 476 } 477 478 static int lan87xx_cable_test_get_status(struct phy_device *phydev, 479 bool *finished) 480 { 481 int rc = 0; 482 483 *finished = false; 484 485 /* check if cable diag was finished */ 486 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_DSP, 487 90, 0); 488 if (rc < 0) 489 return rc; 490 491 if ((rc & 2) == 2) { 492 /* stop cable diag*/ 493 rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE, 494 PHYACC_ATTR_BANK_DSP, 495 90, 0); 496 if (rc < 0) 497 return rc; 498 499 *finished = true; 500 501 return lan87xx_cable_test_report(phydev); 502 } 503 504 return 0; 505 } 506 507 static struct phy_driver microchip_t1_phy_driver[] = { 508 { 509 .phy_id = 0x0007c150, 510 .phy_id_mask = 0xfffffff0, 511 .name = "Microchip LAN87xx T1", 512 .flags = PHY_POLL_CABLE_TEST, 513 514 .features = PHY_BASIC_T1_FEATURES, 515 516 .config_init = lan87xx_config_init, 517 518 .config_intr = lan87xx_phy_config_intr, 519 .handle_interrupt = lan87xx_handle_interrupt, 520 521 .suspend = genphy_suspend, 522 .resume = genphy_resume, 523 .cable_test_start = lan87xx_cable_test_start, 524 .cable_test_get_status = lan87xx_cable_test_get_status, 525 } 526 }; 527 528 module_phy_driver(microchip_t1_phy_driver); 529 530 static struct mdio_device_id __maybe_unused microchip_t1_tbl[] = { 531 { 0x0007c150, 0xfffffff0 }, 532 { } 533 }; 534 535 MODULE_DEVICE_TABLE(mdio, microchip_t1_tbl); 536 537 MODULE_AUTHOR(DRIVER_AUTHOR); 538 MODULE_DESCRIPTION(DRIVER_DESC); 539 MODULE_LICENSE("GPL"); 540