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