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, 136 int port, 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 memcpy(data + i * ETH_GSTRING_LEN, stat->string, 148 ETH_GSTRING_LEN); 149 } 150 return ARRAY_SIZE(mv88e6352_serdes_hw_stats); 151 } 152 153 static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip, 154 struct mv88e6352_serdes_hw_stat *stat) 155 { 156 u64 val = 0; 157 u16 reg; 158 int err; 159 160 err = mv88e6352_serdes_read(chip, stat->reg, ®); 161 if (err) { 162 dev_err(chip->dev, "failed to read statistic\n"); 163 return 0; 164 } 165 166 val = reg; 167 168 if (stat->sizeof_stat == 32) { 169 err = mv88e6352_serdes_read(chip, stat->reg + 1, ®); 170 if (err) { 171 dev_err(chip->dev, "failed to read statistic\n"); 172 return 0; 173 } 174 val = val << 16 | reg; 175 } 176 177 return val; 178 } 179 180 int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, 181 uint64_t *data) 182 { 183 struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port]; 184 struct mv88e6352_serdes_hw_stat *stat; 185 int i, err; 186 u64 value; 187 188 err = mv88e6352_g2_scratch_port_has_serdes(chip, port); 189 if (err <= 0) 190 return err; 191 192 BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) > 193 ARRAY_SIZE(mv88e6xxx_port->serdes_stats)); 194 195 for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) { 196 stat = &mv88e6352_serdes_hw_stats[i]; 197 value = mv88e6352_serdes_get_stat(chip, stat); 198 mv88e6xxx_port->serdes_stats[i] += value; 199 data[i] = mv88e6xxx_port->serdes_stats[i]; 200 } 201 202 return ARRAY_SIZE(mv88e6352_serdes_hw_stats); 203 } 204 205 unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) 206 { 207 return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ); 208 } 209 210 int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port) 211 { 212 int err; 213 214 mv88e6xxx_reg_lock(chip); 215 err = mv88e6352_g2_scratch_port_has_serdes(chip, port); 216 mv88e6xxx_reg_unlock(chip); 217 if (err <= 0) 218 return err; 219 220 return 32 * sizeof(u16); 221 } 222 223 void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p) 224 { 225 u16 *p = _p; 226 u16 reg; 227 int err; 228 int i; 229 230 err = mv88e6352_g2_scratch_port_has_serdes(chip, port); 231 if (err <= 0) 232 return; 233 234 for (i = 0 ; i < 32; i++) { 235 err = mv88e6352_serdes_read(chip, i, ®); 236 if (!err) 237 p[i] = reg; 238 } 239 } 240 241 int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 242 { 243 u8 cmode = chip->ports[port].cmode; 244 int lane = -ENODEV; 245 246 switch (port) { 247 case 5: 248 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 249 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 250 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 251 lane = MV88E6341_PORT5_LANE; 252 break; 253 } 254 255 return lane; 256 } 257 258 int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 259 { 260 u8 cmode = chip->ports[port].cmode; 261 int lane = -ENODEV; 262 263 switch (port) { 264 case 9: 265 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 266 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 267 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 268 lane = MV88E6390_PORT9_LANE0; 269 break; 270 case 10: 271 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 272 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 273 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 274 lane = MV88E6390_PORT10_LANE0; 275 break; 276 } 277 278 return lane; 279 } 280 281 int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 282 { 283 u8 cmode_port = chip->ports[port].cmode; 284 u8 cmode_port10 = chip->ports[10].cmode; 285 u8 cmode_port9 = chip->ports[9].cmode; 286 int lane = -ENODEV; 287 288 switch (port) { 289 case 2: 290 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 291 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 292 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 293 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 294 lane = MV88E6390_PORT9_LANE1; 295 break; 296 case 3: 297 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 298 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 299 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 300 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 301 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 302 lane = MV88E6390_PORT9_LANE2; 303 break; 304 case 4: 305 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 306 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 307 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 308 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 309 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 310 lane = MV88E6390_PORT9_LANE3; 311 break; 312 case 5: 313 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 314 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 315 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 316 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 317 lane = MV88E6390_PORT10_LANE1; 318 break; 319 case 6: 320 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 321 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 322 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 323 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 324 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 325 lane = MV88E6390_PORT10_LANE2; 326 break; 327 case 7: 328 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 329 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 330 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 331 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 332 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 333 lane = MV88E6390_PORT10_LANE3; 334 break; 335 case 9: 336 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 337 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 338 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 339 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI || 340 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 341 lane = MV88E6390_PORT9_LANE0; 342 break; 343 case 10: 344 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 345 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 346 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 347 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI || 348 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 349 lane = MV88E6390_PORT10_LANE0; 350 break; 351 } 352 353 return lane; 354 } 355 356 /* Only Ports 0, 9 and 10 have SERDES lanes. Return the SERDES lane address 357 * a port is using else Returns -ENODEV. 358 */ 359 int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 360 { 361 u8 cmode = chip->ports[port].cmode; 362 int lane = -ENODEV; 363 364 if (port != 0 && port != 9 && port != 10) 365 return -EOPNOTSUPP; 366 367 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 368 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 369 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 370 cmode == MV88E6393X_PORT_STS_CMODE_5GBASER || 371 cmode == MV88E6393X_PORT_STS_CMODE_10GBASER || 372 cmode == MV88E6393X_PORT_STS_CMODE_USXGMII) 373 lane = port; 374 375 return lane; 376 } 377 378 struct mv88e6390_serdes_hw_stat { 379 char string[ETH_GSTRING_LEN]; 380 int reg; 381 }; 382 383 static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats[] = { 384 { "serdes_rx_pkts", 0xf021 }, 385 { "serdes_rx_bytes", 0xf024 }, 386 { "serdes_rx_pkts_error", 0xf027 }, 387 }; 388 389 int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port) 390 { 391 if (mv88e6xxx_serdes_get_lane(chip, port) < 0) 392 return 0; 393 394 return ARRAY_SIZE(mv88e6390_serdes_hw_stats); 395 } 396 397 int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip, 398 int port, uint8_t *data) 399 { 400 struct mv88e6390_serdes_hw_stat *stat; 401 int i; 402 403 if (mv88e6xxx_serdes_get_lane(chip, port) < 0) 404 return 0; 405 406 for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) { 407 stat = &mv88e6390_serdes_hw_stats[i]; 408 memcpy(data + i * ETH_GSTRING_LEN, stat->string, 409 ETH_GSTRING_LEN); 410 } 411 return ARRAY_SIZE(mv88e6390_serdes_hw_stats); 412 } 413 414 static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane, 415 struct mv88e6390_serdes_hw_stat *stat) 416 { 417 u16 reg[3]; 418 int err, i; 419 420 for (i = 0; i < 3; i++) { 421 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 422 stat->reg + i, ®[i]); 423 if (err) { 424 dev_err(chip->dev, "failed to read statistic\n"); 425 return 0; 426 } 427 } 428 429 return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32); 430 } 431 432 int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, 433 uint64_t *data) 434 { 435 struct mv88e6390_serdes_hw_stat *stat; 436 int lane; 437 int i; 438 439 lane = mv88e6xxx_serdes_get_lane(chip, port); 440 if (lane < 0) 441 return 0; 442 443 for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) { 444 stat = &mv88e6390_serdes_hw_stats[i]; 445 data[i] = mv88e6390_serdes_get_stat(chip, lane, stat); 446 } 447 448 return ARRAY_SIZE(mv88e6390_serdes_hw_stats); 449 } 450 451 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) 452 { 453 return irq_find_mapping(chip->g2_irq.domain, port); 454 } 455 456 static const u16 mv88e6390_serdes_regs[] = { 457 /* SERDES common registers */ 458 0xf00a, 0xf00b, 0xf00c, 459 0xf010, 0xf011, 0xf012, 0xf013, 460 0xf016, 0xf017, 0xf018, 461 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f, 462 0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027, 463 0xf028, 0xf029, 464 0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037, 465 0xf038, 0xf039, 466 /* SGMII */ 467 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 468 0x2008, 469 0x200f, 470 0xa000, 0xa001, 0xa002, 0xa003, 471 /* 10Gbase-X */ 472 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 473 0x1008, 474 0x100e, 0x100f, 475 0x1018, 0x1019, 476 0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 477 0x9006, 478 0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016, 479 /* 10Gbase-R */ 480 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027, 481 0x1028, 0x1029, 0x102a, 0x102b, 482 }; 483 484 int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port) 485 { 486 if (mv88e6xxx_serdes_get_lane(chip, port) < 0) 487 return 0; 488 489 return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16); 490 } 491 492 void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p) 493 { 494 u16 *p = _p; 495 int lane; 496 u16 reg; 497 int err; 498 int i; 499 500 lane = mv88e6xxx_serdes_get_lane(chip, port); 501 if (lane < 0) 502 return; 503 504 for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) { 505 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 506 mv88e6390_serdes_regs[i], ®); 507 if (!err) 508 p[i] = reg; 509 } 510 } 511 512 static const int mv88e6352_serdes_p2p_to_reg[] = { 513 /* Index of value in microvolts corresponds to the register value */ 514 14000, 112000, 210000, 308000, 406000, 504000, 602000, 700000, 515 }; 516 517 int mv88e6352_serdes_set_tx_amplitude(struct mv88e6xxx_chip *chip, int port, 518 int val) 519 { 520 bool found = false; 521 u16 ctrl, reg; 522 int err; 523 int i; 524 525 err = mv88e6352_g2_scratch_port_has_serdes(chip, port); 526 if (err <= 0) 527 return err; 528 529 for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_p2p_to_reg); ++i) { 530 if (mv88e6352_serdes_p2p_to_reg[i] == val) { 531 reg = i; 532 found = true; 533 break; 534 } 535 } 536 537 if (!found) 538 return -EINVAL; 539 540 err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_SPEC_CTRL2, &ctrl); 541 if (err) 542 return err; 543 544 ctrl &= ~MV88E6352_SERDES_OUT_AMP_MASK; 545 ctrl |= reg; 546 547 return mv88e6352_serdes_write(chip, MV88E6352_SERDES_SPEC_CTRL2, ctrl); 548 } 549