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 int reg_c45 = MII_ADDR_C45 | device << 16 | reg; 40 41 return mv88e6xxx_phy_read(chip, lane, reg_c45, val); 42 } 43 44 static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip, 45 int lane, int device, int reg, u16 val) 46 { 47 int reg_c45 = MII_ADDR_C45 | device << 16 | reg; 48 49 return mv88e6xxx_phy_write(chip, lane, reg_c45, val); 50 } 51 52 int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane, 53 bool up) 54 { 55 u16 val, new_val; 56 int err; 57 58 err = mv88e6352_serdes_read(chip, MII_BMCR, &val); 59 if (err) 60 return err; 61 62 if (up) 63 new_val = val & ~BMCR_PDOWN; 64 else 65 new_val = val | BMCR_PDOWN; 66 67 if (val != new_val) 68 err = mv88e6352_serdes_write(chip, MII_BMCR, new_val); 69 70 return err; 71 } 72 73 u8 mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 74 { 75 u8 cmode = chip->ports[port].cmode; 76 u8 lane = 0; 77 78 if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX) || 79 (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX) || 80 (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII)) 81 lane = 0xff; /* Unused */ 82 83 return lane; 84 } 85 86 static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port) 87 { 88 if (mv88e6xxx_serdes_get_lane(chip, port)) 89 return true; 90 91 return false; 92 } 93 94 struct mv88e6352_serdes_hw_stat { 95 char string[ETH_GSTRING_LEN]; 96 int sizeof_stat; 97 int reg; 98 }; 99 100 static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = { 101 { "serdes_fibre_rx_error", 16, 21 }, 102 { "serdes_PRBS_error", 32, 24 }, 103 }; 104 105 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port) 106 { 107 if (mv88e6352_port_has_serdes(chip, port)) 108 return ARRAY_SIZE(mv88e6352_serdes_hw_stats); 109 110 return 0; 111 } 112 113 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, 114 int port, uint8_t *data) 115 { 116 struct mv88e6352_serdes_hw_stat *stat; 117 int i; 118 119 if (!mv88e6352_port_has_serdes(chip, port)) 120 return 0; 121 122 for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) { 123 stat = &mv88e6352_serdes_hw_stats[i]; 124 memcpy(data + i * ETH_GSTRING_LEN, stat->string, 125 ETH_GSTRING_LEN); 126 } 127 return ARRAY_SIZE(mv88e6352_serdes_hw_stats); 128 } 129 130 static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip, 131 struct mv88e6352_serdes_hw_stat *stat) 132 { 133 u64 val = 0; 134 u16 reg; 135 int err; 136 137 err = mv88e6352_serdes_read(chip, stat->reg, ®); 138 if (err) { 139 dev_err(chip->dev, "failed to read statistic\n"); 140 return 0; 141 } 142 143 val = reg; 144 145 if (stat->sizeof_stat == 32) { 146 err = mv88e6352_serdes_read(chip, stat->reg + 1, ®); 147 if (err) { 148 dev_err(chip->dev, "failed to read statistic\n"); 149 return 0; 150 } 151 val = val << 16 | reg; 152 } 153 154 return val; 155 } 156 157 int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, 158 uint64_t *data) 159 { 160 struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port]; 161 struct mv88e6352_serdes_hw_stat *stat; 162 u64 value; 163 int i; 164 165 if (!mv88e6352_port_has_serdes(chip, port)) 166 return 0; 167 168 BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) > 169 ARRAY_SIZE(mv88e6xxx_port->serdes_stats)); 170 171 for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) { 172 stat = &mv88e6352_serdes_hw_stats[i]; 173 value = mv88e6352_serdes_get_stat(chip, stat); 174 mv88e6xxx_port->serdes_stats[i] += value; 175 data[i] = mv88e6xxx_port->serdes_stats[i]; 176 } 177 178 return ARRAY_SIZE(mv88e6352_serdes_hw_stats); 179 } 180 181 static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port) 182 { 183 struct dsa_switch *ds = chip->ds; 184 u16 status; 185 bool up; 186 int err; 187 188 err = mv88e6352_serdes_read(chip, MII_BMSR, &status); 189 if (err) 190 return; 191 192 /* Status must be read twice in order to give the current link 193 * status. Otherwise the change in link status since the last 194 * read of the register is returned. 195 */ 196 err = mv88e6352_serdes_read(chip, MII_BMSR, &status); 197 if (err) 198 return; 199 200 up = status & BMSR_LSTATUS; 201 202 dsa_port_phylink_mac_change(ds, port, up); 203 } 204 205 irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, 206 u8 lane) 207 { 208 irqreturn_t ret = IRQ_NONE; 209 u16 status; 210 int err; 211 212 err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status); 213 if (err) 214 return ret; 215 216 if (status & MV88E6352_SERDES_INT_LINK_CHANGE) { 217 ret = IRQ_HANDLED; 218 mv88e6352_serdes_irq_link(chip, port); 219 } 220 221 return ret; 222 } 223 224 int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane, 225 bool enable) 226 { 227 u16 val = 0; 228 229 if (enable) 230 val |= MV88E6352_SERDES_INT_LINK_CHANGE; 231 232 return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, val); 233 } 234 235 unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) 236 { 237 return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ); 238 } 239 240 u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 241 { 242 u8 cmode = chip->ports[port].cmode; 243 u8 lane = 0; 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 u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 258 { 259 u8 cmode = chip->ports[port].cmode; 260 u8 lane = 0; 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 u8 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 u8 lane = 0; 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 /* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */ 356 static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane, 357 bool up) 358 { 359 u16 val, new_val; 360 int err; 361 362 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 363 MV88E6390_PCS_CONTROL_1, &val); 364 365 if (err) 366 return err; 367 368 if (up) 369 new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET | 370 MV88E6390_PCS_CONTROL_1_LOOPBACK | 371 MV88E6390_PCS_CONTROL_1_PDOWN); 372 else 373 new_val = val | MV88E6390_PCS_CONTROL_1_PDOWN; 374 375 if (val != new_val) 376 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 377 MV88E6390_PCS_CONTROL_1, new_val); 378 379 return err; 380 } 381 382 /* Set power up/down for SGMII and 1000Base-X */ 383 static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane, 384 bool up) 385 { 386 u16 val, new_val; 387 int err; 388 389 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 390 MV88E6390_SGMII_CONTROL, &val); 391 if (err) 392 return err; 393 394 if (up) 395 new_val = val & ~(MV88E6390_SGMII_CONTROL_RESET | 396 MV88E6390_SGMII_CONTROL_LOOPBACK | 397 MV88E6390_SGMII_CONTROL_PDOWN); 398 else 399 new_val = val | MV88E6390_SGMII_CONTROL_PDOWN; 400 401 if (val != new_val) 402 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 403 MV88E6390_SGMII_CONTROL, new_val); 404 405 return err; 406 } 407 408 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane, 409 bool up) 410 { 411 u8 cmode = chip->ports[port].cmode; 412 413 switch (cmode) { 414 case MV88E6XXX_PORT_STS_CMODE_SGMII: 415 case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 416 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 417 return mv88e6390_serdes_power_sgmii(chip, lane, up); 418 case MV88E6XXX_PORT_STS_CMODE_XAUI: 419 case MV88E6XXX_PORT_STS_CMODE_RXAUI: 420 return mv88e6390_serdes_power_10g(chip, lane, up); 421 } 422 423 return 0; 424 } 425 426 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip, 427 int port, u8 lane) 428 { 429 u8 cmode = chip->ports[port].cmode; 430 struct dsa_switch *ds = chip->ds; 431 int duplex = DUPLEX_UNKNOWN; 432 int speed = SPEED_UNKNOWN; 433 phy_interface_t mode; 434 int link, err; 435 u16 status; 436 437 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 438 MV88E6390_SGMII_PHY_STATUS, &status); 439 if (err) { 440 dev_err(chip->dev, "can't read SGMII PHY status: %d\n", err); 441 return; 442 } 443 444 link = status & MV88E6390_SGMII_PHY_STATUS_LINK ? 445 LINK_FORCED_UP : LINK_FORCED_DOWN; 446 447 if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) { 448 duplex = status & MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ? 449 DUPLEX_FULL : DUPLEX_HALF; 450 451 switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) { 452 case MV88E6390_SGMII_PHY_STATUS_SPEED_1000: 453 if (cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 454 speed = SPEED_2500; 455 else 456 speed = SPEED_1000; 457 break; 458 case MV88E6390_SGMII_PHY_STATUS_SPEED_100: 459 speed = SPEED_100; 460 break; 461 case MV88E6390_SGMII_PHY_STATUS_SPEED_10: 462 speed = SPEED_10; 463 break; 464 default: 465 dev_err(chip->dev, "invalid PHY speed\n"); 466 return; 467 } 468 } 469 470 switch (cmode) { 471 case MV88E6XXX_PORT_STS_CMODE_SGMII: 472 mode = PHY_INTERFACE_MODE_SGMII; 473 break; 474 case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 475 mode = PHY_INTERFACE_MODE_1000BASEX; 476 break; 477 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 478 mode = PHY_INTERFACE_MODE_2500BASEX; 479 break; 480 default: 481 mode = PHY_INTERFACE_MODE_NA; 482 } 483 484 err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex, 485 PAUSE_OFF, mode); 486 if (err) 487 dev_err(chip->dev, "can't propagate PHY settings to MAC: %d\n", 488 err); 489 else 490 dsa_port_phylink_mac_change(ds, port, link == LINK_FORCED_UP); 491 } 492 493 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip, 494 u8 lane, bool enable) 495 { 496 u16 val = 0; 497 498 if (enable) 499 val |= MV88E6390_SGMII_INT_LINK_DOWN | 500 MV88E6390_SGMII_INT_LINK_UP; 501 502 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 503 MV88E6390_SGMII_INT_ENABLE, val); 504 } 505 506 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane, 507 bool enable) 508 { 509 u8 cmode = chip->ports[port].cmode; 510 511 switch (cmode) { 512 case MV88E6XXX_PORT_STS_CMODE_SGMII: 513 case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 514 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 515 return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable); 516 } 517 518 return 0; 519 } 520 521 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip, 522 u8 lane, u16 *status) 523 { 524 int err; 525 526 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 527 MV88E6390_SGMII_INT_STATUS, status); 528 529 return err; 530 } 531 532 irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, 533 u8 lane) 534 { 535 u8 cmode = chip->ports[port].cmode; 536 irqreturn_t ret = IRQ_NONE; 537 u16 status; 538 int err; 539 540 switch (cmode) { 541 case MV88E6XXX_PORT_STS_CMODE_SGMII: 542 case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 543 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 544 err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status); 545 if (err) 546 return ret; 547 if (status & (MV88E6390_SGMII_INT_LINK_DOWN | 548 MV88E6390_SGMII_INT_LINK_UP)) { 549 ret = IRQ_HANDLED; 550 mv88e6390_serdes_irq_link_sgmii(chip, port, lane); 551 } 552 } 553 554 return ret; 555 } 556 557 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) 558 { 559 return irq_find_mapping(chip->g2_irq.domain, port); 560 } 561