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