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 int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port) 241 { 242 if (!mv88e6352_port_has_serdes(chip, port)) 243 return 0; 244 245 return 32 * sizeof(u16); 246 } 247 248 void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p) 249 { 250 u16 *p = _p; 251 u16 reg; 252 int i; 253 254 if (!mv88e6352_port_has_serdes(chip, port)) 255 return; 256 257 for (i = 0 ; i < 32; i++) { 258 mv88e6352_serdes_read(chip, i, ®); 259 p[i] = reg; 260 } 261 } 262 263 u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 264 { 265 u8 cmode = chip->ports[port].cmode; 266 u8 lane = 0; 267 268 switch (port) { 269 case 5: 270 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 271 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 272 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 273 lane = MV88E6341_PORT5_LANE; 274 break; 275 } 276 277 return lane; 278 } 279 280 u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 281 { 282 u8 cmode = chip->ports[port].cmode; 283 u8 lane = 0; 284 285 switch (port) { 286 case 9: 287 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 288 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 289 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 290 lane = MV88E6390_PORT9_LANE0; 291 break; 292 case 10: 293 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 294 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 295 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 296 lane = MV88E6390_PORT10_LANE0; 297 break; 298 } 299 300 return lane; 301 } 302 303 u8 mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 304 { 305 u8 cmode_port = chip->ports[port].cmode; 306 u8 cmode_port10 = chip->ports[10].cmode; 307 u8 cmode_port9 = chip->ports[9].cmode; 308 u8 lane = 0; 309 310 switch (port) { 311 case 2: 312 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 313 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 314 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 315 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 316 lane = MV88E6390_PORT9_LANE1; 317 break; 318 case 3: 319 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 320 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 321 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 322 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 323 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 324 lane = MV88E6390_PORT9_LANE2; 325 break; 326 case 4: 327 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 328 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 329 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 330 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 331 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 332 lane = MV88E6390_PORT9_LANE3; 333 break; 334 case 5: 335 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 336 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 337 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 338 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 339 lane = MV88E6390_PORT10_LANE1; 340 break; 341 case 6: 342 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 343 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 344 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 345 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 346 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 347 lane = MV88E6390_PORT10_LANE2; 348 break; 349 case 7: 350 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 351 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 352 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 353 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 354 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 355 lane = MV88E6390_PORT10_LANE3; 356 break; 357 case 9: 358 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 359 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 360 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 361 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI || 362 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 363 lane = MV88E6390_PORT9_LANE0; 364 break; 365 case 10: 366 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 367 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 368 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 369 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI || 370 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 371 lane = MV88E6390_PORT10_LANE0; 372 break; 373 } 374 375 return lane; 376 } 377 378 /* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */ 379 static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane, 380 bool up) 381 { 382 u16 val, new_val; 383 int err; 384 385 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 386 MV88E6390_PCS_CONTROL_1, &val); 387 388 if (err) 389 return err; 390 391 if (up) 392 new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET | 393 MV88E6390_PCS_CONTROL_1_LOOPBACK | 394 MV88E6390_PCS_CONTROL_1_PDOWN); 395 else 396 new_val = val | MV88E6390_PCS_CONTROL_1_PDOWN; 397 398 if (val != new_val) 399 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 400 MV88E6390_PCS_CONTROL_1, new_val); 401 402 return err; 403 } 404 405 /* Set power up/down for SGMII and 1000Base-X */ 406 static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane, 407 bool up) 408 { 409 u16 val, new_val; 410 int err; 411 412 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 413 MV88E6390_SGMII_CONTROL, &val); 414 if (err) 415 return err; 416 417 if (up) 418 new_val = val & ~(MV88E6390_SGMII_CONTROL_RESET | 419 MV88E6390_SGMII_CONTROL_LOOPBACK | 420 MV88E6390_SGMII_CONTROL_PDOWN); 421 else 422 new_val = val | MV88E6390_SGMII_CONTROL_PDOWN; 423 424 if (val != new_val) 425 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 426 MV88E6390_SGMII_CONTROL, new_val); 427 428 return err; 429 } 430 431 struct mv88e6390_serdes_hw_stat { 432 char string[ETH_GSTRING_LEN]; 433 int reg; 434 }; 435 436 static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats[] = { 437 { "serdes_rx_pkts", 0xf021 }, 438 { "serdes_rx_bytes", 0xf024 }, 439 { "serdes_rx_pkts_error", 0xf027 }, 440 }; 441 442 int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port) 443 { 444 if (mv88e6390_serdes_get_lane(chip, port) == 0) 445 return 0; 446 447 return ARRAY_SIZE(mv88e6390_serdes_hw_stats); 448 } 449 450 int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip, 451 int port, uint8_t *data) 452 { 453 struct mv88e6390_serdes_hw_stat *stat; 454 int i; 455 456 if (mv88e6390_serdes_get_lane(chip, port) == 0) 457 return 0; 458 459 for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) { 460 stat = &mv88e6390_serdes_hw_stats[i]; 461 memcpy(data + i * ETH_GSTRING_LEN, stat->string, 462 ETH_GSTRING_LEN); 463 } 464 return ARRAY_SIZE(mv88e6390_serdes_hw_stats); 465 } 466 467 static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane, 468 struct mv88e6390_serdes_hw_stat *stat) 469 { 470 u16 reg[3]; 471 int err, i; 472 473 for (i = 0; i < 3; i++) { 474 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 475 stat->reg + i, ®[i]); 476 if (err) { 477 dev_err(chip->dev, "failed to read statistic\n"); 478 return 0; 479 } 480 } 481 482 return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32); 483 } 484 485 int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, 486 uint64_t *data) 487 { 488 struct mv88e6390_serdes_hw_stat *stat; 489 int lane; 490 int i; 491 492 lane = mv88e6390_serdes_get_lane(chip, port); 493 if (lane == 0) 494 return 0; 495 496 for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) { 497 stat = &mv88e6390_serdes_hw_stats[i]; 498 data[i] = mv88e6390_serdes_get_stat(chip, lane, stat); 499 } 500 501 return ARRAY_SIZE(mv88e6390_serdes_hw_stats); 502 } 503 504 static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip *chip, u8 lane) 505 { 506 u16 reg; 507 int err; 508 509 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 510 MV88E6390_PG_CONTROL, ®); 511 if (err) 512 return err; 513 514 reg |= MV88E6390_PG_CONTROL_ENABLE_PC; 515 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 516 MV88E6390_PG_CONTROL, reg); 517 } 518 519 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane, 520 bool up) 521 { 522 u8 cmode = chip->ports[port].cmode; 523 int err = 0; 524 525 switch (cmode) { 526 case MV88E6XXX_PORT_STS_CMODE_SGMII: 527 case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 528 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 529 err = mv88e6390_serdes_power_sgmii(chip, lane, up); 530 break; 531 case MV88E6XXX_PORT_STS_CMODE_XAUI: 532 case MV88E6XXX_PORT_STS_CMODE_RXAUI: 533 err = mv88e6390_serdes_power_10g(chip, lane, up); 534 break; 535 } 536 537 if (!err && up) 538 err = mv88e6390_serdes_enable_checker(chip, lane); 539 540 return err; 541 } 542 543 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip, 544 int port, u8 lane) 545 { 546 u8 cmode = chip->ports[port].cmode; 547 struct dsa_switch *ds = chip->ds; 548 int duplex = DUPLEX_UNKNOWN; 549 int speed = SPEED_UNKNOWN; 550 phy_interface_t mode; 551 int link, err; 552 u16 status; 553 554 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 555 MV88E6390_SGMII_PHY_STATUS, &status); 556 if (err) { 557 dev_err(chip->dev, "can't read SGMII PHY status: %d\n", err); 558 return; 559 } 560 561 link = status & MV88E6390_SGMII_PHY_STATUS_LINK ? 562 LINK_FORCED_UP : LINK_FORCED_DOWN; 563 564 if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) { 565 duplex = status & MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ? 566 DUPLEX_FULL : DUPLEX_HALF; 567 568 switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) { 569 case MV88E6390_SGMII_PHY_STATUS_SPEED_1000: 570 if (cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 571 speed = SPEED_2500; 572 else 573 speed = SPEED_1000; 574 break; 575 case MV88E6390_SGMII_PHY_STATUS_SPEED_100: 576 speed = SPEED_100; 577 break; 578 case MV88E6390_SGMII_PHY_STATUS_SPEED_10: 579 speed = SPEED_10; 580 break; 581 default: 582 dev_err(chip->dev, "invalid PHY speed\n"); 583 return; 584 } 585 } 586 587 switch (cmode) { 588 case MV88E6XXX_PORT_STS_CMODE_SGMII: 589 mode = PHY_INTERFACE_MODE_SGMII; 590 break; 591 case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 592 mode = PHY_INTERFACE_MODE_1000BASEX; 593 break; 594 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 595 mode = PHY_INTERFACE_MODE_2500BASEX; 596 break; 597 default: 598 mode = PHY_INTERFACE_MODE_NA; 599 } 600 601 err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex, 602 PAUSE_OFF, mode); 603 if (err) 604 dev_err(chip->dev, "can't propagate PHY settings to MAC: %d\n", 605 err); 606 else 607 dsa_port_phylink_mac_change(ds, port, link == LINK_FORCED_UP); 608 } 609 610 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip, 611 u8 lane, bool enable) 612 { 613 u16 val = 0; 614 615 if (enable) 616 val |= MV88E6390_SGMII_INT_LINK_DOWN | 617 MV88E6390_SGMII_INT_LINK_UP; 618 619 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 620 MV88E6390_SGMII_INT_ENABLE, val); 621 } 622 623 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane, 624 bool enable) 625 { 626 u8 cmode = chip->ports[port].cmode; 627 628 switch (cmode) { 629 case MV88E6XXX_PORT_STS_CMODE_SGMII: 630 case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 631 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 632 return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable); 633 } 634 635 return 0; 636 } 637 638 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip, 639 u8 lane, u16 *status) 640 { 641 int err; 642 643 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 644 MV88E6390_SGMII_INT_STATUS, status); 645 646 return err; 647 } 648 649 irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, 650 u8 lane) 651 { 652 u8 cmode = chip->ports[port].cmode; 653 irqreturn_t ret = IRQ_NONE; 654 u16 status; 655 int err; 656 657 switch (cmode) { 658 case MV88E6XXX_PORT_STS_CMODE_SGMII: 659 case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 660 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 661 err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status); 662 if (err) 663 return ret; 664 if (status & (MV88E6390_SGMII_INT_LINK_DOWN | 665 MV88E6390_SGMII_INT_LINK_UP)) { 666 ret = IRQ_HANDLED; 667 mv88e6390_serdes_irq_link_sgmii(chip, port, lane); 668 } 669 } 670 671 return ret; 672 } 673 674 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) 675 { 676 return irq_find_mapping(chip->g2_irq.domain, port); 677 } 678 679 static const u16 mv88e6390_serdes_regs[] = { 680 /* SERDES common registers */ 681 0xf00a, 0xf00b, 0xf00c, 682 0xf010, 0xf011, 0xf012, 0xf013, 683 0xf016, 0xf017, 0xf018, 684 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f, 685 0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027, 686 0xf028, 0xf029, 687 0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037, 688 0xf038, 0xf039, 689 /* SGMII */ 690 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 691 0x2008, 692 0x200f, 693 0xa000, 0xa001, 0xa002, 0xa003, 694 /* 10Gbase-X */ 695 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 696 0x1008, 697 0x100e, 0x100f, 698 0x1018, 0x1019, 699 0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 700 0x9006, 701 0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016, 702 /* 10Gbase-R */ 703 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027, 704 0x1028, 0x1029, 0x102a, 0x102b, 705 }; 706 707 int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port) 708 { 709 if (mv88e6xxx_serdes_get_lane(chip, port) == 0) 710 return 0; 711 712 return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16); 713 } 714 715 void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p) 716 { 717 u16 *p = _p; 718 int lane; 719 u16 reg; 720 int i; 721 722 lane = mv88e6xxx_serdes_get_lane(chip, port); 723 if (lane == 0) 724 return; 725 726 for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) { 727 mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 728 mv88e6390_serdes_regs[i], ®); 729 p[i] = reg; 730 } 731 } 732