1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Marvell 88E6xxx SERDES manipulation, via SMI bus 4 * 5 * Copyright (c) 2008 Marvell Semiconductor 6 * 7 * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch> 8 */ 9 10 #include <linux/interrupt.h> 11 #include <linux/irqdomain.h> 12 #include <linux/mii.h> 13 14 #include "chip.h" 15 #include "global2.h" 16 #include "phy.h" 17 #include "port.h" 18 #include "serdes.h" 19 20 static int mv88e6352_serdes_read(struct mv88e6xxx_chip *chip, int reg, 21 u16 *val) 22 { 23 return mv88e6xxx_phy_page_read(chip, MV88E6352_ADDR_SERDES, 24 MV88E6352_SERDES_PAGE_FIBER, 25 reg, val); 26 } 27 28 static int mv88e6352_serdes_write(struct mv88e6xxx_chip *chip, int reg, 29 u16 val) 30 { 31 return mv88e6xxx_phy_page_write(chip, MV88E6352_ADDR_SERDES, 32 MV88E6352_SERDES_PAGE_FIBER, 33 reg, val); 34 } 35 36 static int mv88e6390_serdes_read(struct mv88e6xxx_chip *chip, 37 int lane, int device, int reg, u16 *val) 38 { 39 return mv88e6xxx_phy_read_c45(chip, lane, device, reg, val); 40 } 41 42 int mv88e6xxx_pcs_decode_state(struct device *dev, u16 bmsr, u16 lpa, 43 u16 status, struct phylink_link_state *state) 44 { 45 state->link = false; 46 47 /* If the BMSR reports that the link had failed, report this to 48 * phylink. 49 */ 50 if (!(bmsr & BMSR_LSTATUS)) 51 return 0; 52 53 state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK); 54 state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE); 55 56 if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) { 57 /* The Spped and Duplex Resolved register is 1 if AN is enabled 58 * and complete, or if AN is disabled. So with disabled AN we 59 * still get here on link up. 60 */ 61 state->duplex = status & 62 MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ? 63 DUPLEX_FULL : DUPLEX_HALF; 64 65 if (status & MV88E6390_SGMII_PHY_STATUS_TX_PAUSE) 66 state->pause |= MLO_PAUSE_TX; 67 if (status & MV88E6390_SGMII_PHY_STATUS_RX_PAUSE) 68 state->pause |= MLO_PAUSE_RX; 69 70 switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) { 71 case MV88E6390_SGMII_PHY_STATUS_SPEED_1000: 72 if (state->interface == PHY_INTERFACE_MODE_2500BASEX) 73 state->speed = SPEED_2500; 74 else 75 state->speed = SPEED_1000; 76 break; 77 case MV88E6390_SGMII_PHY_STATUS_SPEED_100: 78 state->speed = SPEED_100; 79 break; 80 case MV88E6390_SGMII_PHY_STATUS_SPEED_10: 81 state->speed = SPEED_10; 82 break; 83 default: 84 dev_err(dev, "invalid PHY speed\n"); 85 return -EINVAL; 86 } 87 } else if (state->link && 88 state->interface != PHY_INTERFACE_MODE_SGMII) { 89 /* If Speed and Duplex Resolved register is 0 and link is up, it 90 * means that AN was enabled, but link partner had it disabled 91 * and the PHY invoked the Auto-Negotiation Bypass feature and 92 * linked anyway. 93 */ 94 state->duplex = DUPLEX_FULL; 95 if (state->interface == PHY_INTERFACE_MODE_2500BASEX) 96 state->speed = SPEED_2500; 97 else 98 state->speed = SPEED_1000; 99 } else { 100 state->link = false; 101 } 102 103 if (state->interface == PHY_INTERFACE_MODE_2500BASEX) 104 mii_lpa_mod_linkmode_x(state->lp_advertising, lpa, 105 ETHTOOL_LINK_MODE_2500baseX_Full_BIT); 106 else if (state->interface == PHY_INTERFACE_MODE_1000BASEX) 107 mii_lpa_mod_linkmode_x(state->lp_advertising, lpa, 108 ETHTOOL_LINK_MODE_1000baseX_Full_BIT); 109 110 return 0; 111 } 112 113 struct mv88e6352_serdes_hw_stat { 114 char string[ETH_GSTRING_LEN]; 115 int sizeof_stat; 116 int reg; 117 }; 118 119 static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = { 120 { "serdes_fibre_rx_error", 16, 21 }, 121 { "serdes_PRBS_error", 32, 24 }, 122 }; 123 124 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port) 125 { 126 int err; 127 128 err = mv88e6352_g2_scratch_port_has_serdes(chip, port); 129 if (err <= 0) 130 return err; 131 132 return ARRAY_SIZE(mv88e6352_serdes_hw_stats); 133 } 134 135 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, int port, 136 uint8_t **data) 137 { 138 struct mv88e6352_serdes_hw_stat *stat; 139 int err, i; 140 141 err = mv88e6352_g2_scratch_port_has_serdes(chip, port); 142 if (err <= 0) 143 return err; 144 145 for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) { 146 stat = &mv88e6352_serdes_hw_stats[i]; 147 ethtool_puts(data, stat->string); 148 } 149 return ARRAY_SIZE(mv88e6352_serdes_hw_stats); 150 } 151 152 static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip, 153 struct mv88e6352_serdes_hw_stat *stat) 154 { 155 u64 val = 0; 156 u16 reg; 157 int err; 158 159 err = mv88e6352_serdes_read(chip, stat->reg, ®); 160 if (err) { 161 dev_err(chip->dev, "failed to read statistic\n"); 162 return 0; 163 } 164 165 val = reg; 166 167 if (stat->sizeof_stat == 32) { 168 err = mv88e6352_serdes_read(chip, stat->reg + 1, ®); 169 if (err) { 170 dev_err(chip->dev, "failed to read statistic\n"); 171 return 0; 172 } 173 val = val << 16 | reg; 174 } 175 176 return val; 177 } 178 179 size_t mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, 180 uint64_t *data) 181 { 182 struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port]; 183 struct mv88e6352_serdes_hw_stat *stat; 184 int i, err; 185 u64 value; 186 187 err = mv88e6352_g2_scratch_port_has_serdes(chip, port); 188 if (err <= 0) 189 return 0; 190 191 BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) > 192 ARRAY_SIZE(mv88e6xxx_port->serdes_stats)); 193 194 for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) { 195 stat = &mv88e6352_serdes_hw_stats[i]; 196 value = mv88e6352_serdes_get_stat(chip, stat); 197 mv88e6xxx_port->serdes_stats[i] += value; 198 data[i] = mv88e6xxx_port->serdes_stats[i]; 199 } 200 201 return ARRAY_SIZE(mv88e6352_serdes_hw_stats); 202 } 203 204 unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) 205 { 206 return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ); 207 } 208 209 int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port) 210 { 211 int err; 212 213 mv88e6xxx_reg_lock(chip); 214 err = mv88e6352_g2_scratch_port_has_serdes(chip, port); 215 mv88e6xxx_reg_unlock(chip); 216 if (err <= 0) 217 return err; 218 219 return 32 * sizeof(u16); 220 } 221 222 void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p) 223 { 224 u16 *p = _p; 225 u16 reg; 226 int err; 227 int i; 228 229 err = mv88e6352_g2_scratch_port_has_serdes(chip, port); 230 if (err <= 0) 231 return; 232 233 for (i = 0 ; i < 32; i++) { 234 err = mv88e6352_serdes_read(chip, i, ®); 235 if (!err) 236 p[i] = reg; 237 } 238 } 239 240 int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 241 { 242 u8 cmode = chip->ports[port].cmode; 243 int lane = -ENODEV; 244 245 switch (port) { 246 case 5: 247 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 248 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 249 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 250 lane = MV88E6341_PORT5_LANE; 251 break; 252 } 253 254 return lane; 255 } 256 257 int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 258 { 259 u8 cmode = chip->ports[port].cmode; 260 int lane = -ENODEV; 261 262 switch (port) { 263 case 9: 264 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 265 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 266 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 267 lane = MV88E6390_PORT9_LANE0; 268 break; 269 case 10: 270 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 271 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 272 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 273 lane = MV88E6390_PORT10_LANE0; 274 break; 275 } 276 277 return lane; 278 } 279 280 int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 281 { 282 u8 cmode_port = chip->ports[port].cmode; 283 u8 cmode_port10 = chip->ports[10].cmode; 284 u8 cmode_port9 = chip->ports[9].cmode; 285 int lane = -ENODEV; 286 287 switch (port) { 288 case 2: 289 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 290 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 291 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 292 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 293 lane = MV88E6390_PORT9_LANE1; 294 break; 295 case 3: 296 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 297 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 298 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 299 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 300 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 301 lane = MV88E6390_PORT9_LANE2; 302 break; 303 case 4: 304 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 305 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 306 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 307 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 308 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 309 lane = MV88E6390_PORT9_LANE3; 310 break; 311 case 5: 312 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 313 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 314 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 315 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 316 lane = MV88E6390_PORT10_LANE1; 317 break; 318 case 6: 319 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 320 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 321 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 322 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 323 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 324 lane = MV88E6390_PORT10_LANE2; 325 break; 326 case 7: 327 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 328 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 329 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 330 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 331 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 332 lane = MV88E6390_PORT10_LANE3; 333 break; 334 case 9: 335 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 336 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 337 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 338 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI || 339 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 340 lane = MV88E6390_PORT9_LANE0; 341 break; 342 case 10: 343 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 344 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 345 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 346 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI || 347 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 348 lane = MV88E6390_PORT10_LANE0; 349 break; 350 } 351 352 return lane; 353 } 354 355 /* Only Ports 0, 9 and 10 have SERDES lanes. Return the SERDES lane address 356 * a port is using else Returns -ENODEV. 357 */ 358 int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 359 { 360 u8 cmode = chip->ports[port].cmode; 361 int lane = -ENODEV; 362 363 if (port != 0 && port != 9 && port != 10) 364 return -EOPNOTSUPP; 365 366 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 367 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 368 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 369 cmode == MV88E6393X_PORT_STS_CMODE_5GBASER || 370 cmode == MV88E6393X_PORT_STS_CMODE_10GBASER || 371 cmode == MV88E6393X_PORT_STS_CMODE_USXGMII) 372 lane = port; 373 374 return lane; 375 } 376 377 struct mv88e6390_serdes_hw_stat { 378 char string[ETH_GSTRING_LEN]; 379 int reg; 380 }; 381 382 static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats[] = { 383 { "serdes_rx_pkts", 0xf021 }, 384 { "serdes_rx_bytes", 0xf024 }, 385 { "serdes_rx_pkts_error", 0xf027 }, 386 }; 387 388 int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port) 389 { 390 if (mv88e6xxx_serdes_get_lane(chip, port) < 0) 391 return 0; 392 393 return ARRAY_SIZE(mv88e6390_serdes_hw_stats); 394 } 395 396 int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip, int port, 397 uint8_t **data) 398 { 399 struct mv88e6390_serdes_hw_stat *stat; 400 int i; 401 402 if (mv88e6xxx_serdes_get_lane(chip, port) < 0) 403 return 0; 404 405 for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) { 406 stat = &mv88e6390_serdes_hw_stats[i]; 407 ethtool_puts(data, stat->string); 408 } 409 return ARRAY_SIZE(mv88e6390_serdes_hw_stats); 410 } 411 412 static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane, 413 struct mv88e6390_serdes_hw_stat *stat) 414 { 415 u16 reg[3]; 416 int err, i; 417 418 for (i = 0; i < 3; i++) { 419 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 420 stat->reg + i, ®[i]); 421 if (err) { 422 dev_err(chip->dev, "failed to read statistic\n"); 423 return 0; 424 } 425 } 426 427 return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32); 428 } 429 430 size_t mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, 431 uint64_t *data) 432 { 433 struct mv88e6390_serdes_hw_stat *stat; 434 int lane; 435 int i; 436 437 lane = mv88e6xxx_serdes_get_lane(chip, port); 438 if (lane < 0) 439 return 0; 440 441 for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) { 442 stat = &mv88e6390_serdes_hw_stats[i]; 443 data[i] = mv88e6390_serdes_get_stat(chip, lane, stat); 444 } 445 446 return ARRAY_SIZE(mv88e6390_serdes_hw_stats); 447 } 448 449 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) 450 { 451 return irq_find_mapping(chip->g2_irq.domain, port); 452 } 453 454 static const u16 mv88e6390_serdes_regs[] = { 455 /* SERDES common registers */ 456 0xf00a, 0xf00b, 0xf00c, 457 0xf010, 0xf011, 0xf012, 0xf013, 458 0xf016, 0xf017, 0xf018, 459 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f, 460 0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027, 461 0xf028, 0xf029, 462 0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037, 463 0xf038, 0xf039, 464 /* SGMII */ 465 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 466 0x2008, 467 0x200f, 468 0xa000, 0xa001, 0xa002, 0xa003, 469 /* 10Gbase-X */ 470 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 471 0x1008, 472 0x100e, 0x100f, 473 0x1018, 0x1019, 474 0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 475 0x9006, 476 0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016, 477 /* 10Gbase-R */ 478 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027, 479 0x1028, 0x1029, 0x102a, 0x102b, 480 }; 481 482 int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port) 483 { 484 if (mv88e6xxx_serdes_get_lane(chip, port) < 0) 485 return 0; 486 487 return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16); 488 } 489 490 void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p) 491 { 492 u16 *p = _p; 493 int lane; 494 u16 reg; 495 int err; 496 int i; 497 498 lane = mv88e6xxx_serdes_get_lane(chip, port); 499 if (lane < 0) 500 return; 501 502 for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) { 503 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 504 mv88e6390_serdes_regs[i], ®); 505 if (!err) 506 p[i] = reg; 507 } 508 } 509 510 static const int mv88e6352_serdes_p2p_to_reg[] = { 511 /* Index of value in microvolts corresponds to the register value */ 512 14000, 112000, 210000, 308000, 406000, 504000, 602000, 700000, 513 }; 514 515 int mv88e6352_serdes_set_tx_amplitude(struct mv88e6xxx_chip *chip, int port, 516 int val) 517 { 518 bool found = false; 519 u16 ctrl, reg; 520 int err; 521 int i; 522 523 err = mv88e6352_g2_scratch_port_has_serdes(chip, port); 524 if (err <= 0) 525 return err; 526 527 for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_p2p_to_reg); ++i) { 528 if (mv88e6352_serdes_p2p_to_reg[i] == val) { 529 reg = i; 530 found = true; 531 break; 532 } 533 } 534 535 if (!found) 536 return -EINVAL; 537 538 err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_SPEC_CTRL2, &ctrl); 539 if (err) 540 return err; 541 542 ctrl &= ~MV88E6352_SERDES_OUT_AMP_MASK; 543 ctrl |= reg; 544 545 return mv88e6352_serdes_write(chip, MV88E6352_SERDES_SPEC_CTRL2, ctrl); 546 } 547