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 static irqreturn_t mv88e6352_serdes_thread_fn(int irq, void *dev_id) 206 { 207 struct mv88e6xxx_port *port = dev_id; 208 struct mv88e6xxx_chip *chip = port->chip; 209 irqreturn_t ret = IRQ_NONE; 210 u16 status; 211 int err; 212 213 mv88e6xxx_reg_lock(chip); 214 215 err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status); 216 if (err) 217 goto out; 218 219 if (status & MV88E6352_SERDES_INT_LINK_CHANGE) { 220 ret = IRQ_HANDLED; 221 mv88e6352_serdes_irq_link(chip, port->port); 222 } 223 out: 224 mv88e6xxx_reg_unlock(chip); 225 226 return ret; 227 } 228 229 static int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip) 230 { 231 return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, 232 MV88E6352_SERDES_INT_LINK_CHANGE); 233 } 234 235 static int mv88e6352_serdes_irq_disable(struct mv88e6xxx_chip *chip) 236 { 237 return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, 0); 238 } 239 240 unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) 241 { 242 return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ); 243 } 244 245 int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port) 246 { 247 unsigned int irq; 248 int err; 249 250 if (!mv88e6352_port_has_serdes(chip, port)) 251 return 0; 252 253 irq = mv88e6xxx_serdes_irq_mapping(chip, port); 254 if (!irq) 255 return 0; 256 257 chip->ports[port].serdes_irq = irq; 258 259 /* Requesting the IRQ will trigger irq callbacks. So we cannot 260 * hold the reg_lock. 261 */ 262 mv88e6xxx_reg_unlock(chip); 263 err = request_threaded_irq(chip->ports[port].serdes_irq, NULL, 264 mv88e6352_serdes_thread_fn, 265 IRQF_ONESHOT, "mv88e6xxx-serdes", 266 &chip->ports[port]); 267 mv88e6xxx_reg_lock(chip); 268 269 if (err) { 270 dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n", 271 err); 272 return err; 273 } 274 275 return mv88e6352_serdes_irq_enable(chip); 276 } 277 278 void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port) 279 { 280 if (!mv88e6352_port_has_serdes(chip, port)) 281 return; 282 283 mv88e6352_serdes_irq_disable(chip); 284 285 /* Freeing the IRQ will trigger irq callbacks. So we cannot 286 * hold the reg_lock. 287 */ 288 mv88e6xxx_reg_unlock(chip); 289 free_irq(chip->ports[port].serdes_irq, &chip->ports[port]); 290 mv88e6xxx_reg_lock(chip); 291 292 chip->ports[port].serdes_irq = 0; 293 } 294 295 u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 296 { 297 u8 cmode = chip->ports[port].cmode; 298 u8 lane = 0; 299 300 switch (port) { 301 case 5: 302 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 303 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 304 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 305 lane = MV88E6341_PORT5_LANE; 306 break; 307 } 308 309 return lane; 310 } 311 312 u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 313 { 314 u8 cmode = chip->ports[port].cmode; 315 u8 lane = 0; 316 317 switch (port) { 318 case 9: 319 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 320 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 321 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 322 lane = MV88E6390_PORT9_LANE0; 323 break; 324 case 10: 325 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 326 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 327 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 328 lane = MV88E6390_PORT10_LANE0; 329 break; 330 } 331 332 return lane; 333 } 334 335 u8 mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 336 { 337 u8 cmode_port = chip->ports[port].cmode; 338 u8 cmode_port10 = chip->ports[10].cmode; 339 u8 cmode_port9 = chip->ports[9].cmode; 340 u8 lane = 0; 341 342 switch (port) { 343 case 2: 344 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 345 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 346 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 347 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 348 lane = MV88E6390_PORT9_LANE1; 349 break; 350 case 3: 351 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 352 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 353 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 354 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 355 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 356 lane = MV88E6390_PORT9_LANE2; 357 break; 358 case 4: 359 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 360 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 361 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 362 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 363 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 364 lane = MV88E6390_PORT9_LANE3; 365 break; 366 case 5: 367 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 368 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 369 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 370 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 371 lane = MV88E6390_PORT10_LANE1; 372 break; 373 case 6: 374 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 375 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 376 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 377 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 378 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 379 lane = MV88E6390_PORT10_LANE2; 380 break; 381 case 7: 382 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 383 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 384 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 385 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 386 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX) 387 lane = MV88E6390_PORT10_LANE3; 388 break; 389 case 9: 390 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 391 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 392 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 393 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI || 394 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 395 lane = MV88E6390_PORT9_LANE0; 396 break; 397 case 10: 398 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX || 399 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 400 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 401 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI || 402 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 403 lane = MV88E6390_PORT10_LANE0; 404 break; 405 } 406 407 return lane; 408 } 409 410 /* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */ 411 static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane, 412 bool up) 413 { 414 u16 val, new_val; 415 int err; 416 417 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 418 MV88E6390_PCS_CONTROL_1, &val); 419 420 if (err) 421 return err; 422 423 if (up) 424 new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET | 425 MV88E6390_PCS_CONTROL_1_LOOPBACK | 426 MV88E6390_PCS_CONTROL_1_PDOWN); 427 else 428 new_val = val | MV88E6390_PCS_CONTROL_1_PDOWN; 429 430 if (val != new_val) 431 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 432 MV88E6390_PCS_CONTROL_1, new_val); 433 434 return err; 435 } 436 437 /* Set power up/down for SGMII and 1000Base-X */ 438 static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane, 439 bool up) 440 { 441 u16 val, new_val; 442 int err; 443 444 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 445 MV88E6390_SGMII_CONTROL, &val); 446 if (err) 447 return err; 448 449 if (up) 450 new_val = val & ~(MV88E6390_SGMII_CONTROL_RESET | 451 MV88E6390_SGMII_CONTROL_LOOPBACK | 452 MV88E6390_SGMII_CONTROL_PDOWN); 453 else 454 new_val = val | MV88E6390_SGMII_CONTROL_PDOWN; 455 456 if (val != new_val) 457 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 458 MV88E6390_SGMII_CONTROL, new_val); 459 460 return err; 461 } 462 463 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane, 464 bool up) 465 { 466 u8 cmode = chip->ports[port].cmode; 467 468 switch (cmode) { 469 case MV88E6XXX_PORT_STS_CMODE_SGMII: 470 case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 471 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 472 return mv88e6390_serdes_power_sgmii(chip, lane, up); 473 case MV88E6XXX_PORT_STS_CMODE_XAUI: 474 case MV88E6XXX_PORT_STS_CMODE_RXAUI: 475 return mv88e6390_serdes_power_10g(chip, lane, up); 476 } 477 478 return 0; 479 } 480 481 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip, 482 int port, u8 lane) 483 { 484 u8 cmode = chip->ports[port].cmode; 485 struct dsa_switch *ds = chip->ds; 486 int duplex = DUPLEX_UNKNOWN; 487 int speed = SPEED_UNKNOWN; 488 phy_interface_t mode; 489 int link, err; 490 u16 status; 491 492 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 493 MV88E6390_SGMII_PHY_STATUS, &status); 494 if (err) { 495 dev_err(chip->dev, "can't read SGMII PHY status: %d\n", err); 496 return; 497 } 498 499 link = status & MV88E6390_SGMII_PHY_STATUS_LINK ? 500 LINK_FORCED_UP : LINK_FORCED_DOWN; 501 502 if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) { 503 duplex = status & MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ? 504 DUPLEX_FULL : DUPLEX_HALF; 505 506 switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) { 507 case MV88E6390_SGMII_PHY_STATUS_SPEED_1000: 508 if (cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 509 speed = SPEED_2500; 510 else 511 speed = SPEED_1000; 512 break; 513 case MV88E6390_SGMII_PHY_STATUS_SPEED_100: 514 speed = SPEED_100; 515 break; 516 case MV88E6390_SGMII_PHY_STATUS_SPEED_10: 517 speed = SPEED_10; 518 break; 519 default: 520 dev_err(chip->dev, "invalid PHY speed\n"); 521 return; 522 } 523 } 524 525 switch (cmode) { 526 case MV88E6XXX_PORT_STS_CMODE_SGMII: 527 mode = PHY_INTERFACE_MODE_SGMII; 528 break; 529 case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 530 mode = PHY_INTERFACE_MODE_1000BASEX; 531 break; 532 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 533 mode = PHY_INTERFACE_MODE_2500BASEX; 534 break; 535 default: 536 mode = PHY_INTERFACE_MODE_NA; 537 } 538 539 err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex, 540 PAUSE_OFF, mode); 541 if (err) 542 dev_err(chip->dev, "can't propagate PHY settings to MAC: %d\n", 543 err); 544 else 545 dsa_port_phylink_mac_change(ds, port, link == LINK_FORCED_UP); 546 } 547 548 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip, 549 u8 lane) 550 { 551 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 552 MV88E6390_SGMII_INT_ENABLE, 553 MV88E6390_SGMII_INT_LINK_DOWN | 554 MV88E6390_SGMII_INT_LINK_UP); 555 } 556 557 static int mv88e6390_serdes_irq_disable_sgmii(struct mv88e6xxx_chip *chip, 558 u8 lane) 559 { 560 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 561 MV88E6390_SGMII_INT_ENABLE, 0); 562 } 563 564 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, 565 u8 lane) 566 { 567 u8 cmode = chip->ports[port].cmode; 568 int err = 0; 569 570 switch (cmode) { 571 case MV88E6XXX_PORT_STS_CMODE_SGMII: 572 case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 573 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 574 err = mv88e6390_serdes_irq_enable_sgmii(chip, lane); 575 } 576 577 return err; 578 } 579 580 int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port, 581 u8 lane) 582 { 583 u8 cmode = chip->ports[port].cmode; 584 int err = 0; 585 586 switch (cmode) { 587 case MV88E6XXX_PORT_STS_CMODE_SGMII: 588 case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 589 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 590 err = mv88e6390_serdes_irq_disable_sgmii(chip, lane); 591 } 592 593 return err; 594 } 595 596 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip, 597 u8 lane, u16 *status) 598 { 599 int err; 600 601 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 602 MV88E6390_SGMII_INT_STATUS, status); 603 604 return err; 605 } 606 607 static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id) 608 { 609 struct mv88e6xxx_port *port = dev_id; 610 struct mv88e6xxx_chip *chip = port->chip; 611 irqreturn_t ret = IRQ_NONE; 612 u8 cmode = port->cmode; 613 u16 status; 614 int err; 615 u8 lane; 616 617 mv88e6xxx_reg_lock(chip); 618 619 lane = mv88e6xxx_serdes_get_lane(chip, port->port); 620 if (!lane) 621 goto out; 622 623 switch (cmode) { 624 case MV88E6XXX_PORT_STS_CMODE_SGMII: 625 case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 626 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 627 err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status); 628 if (err) 629 goto out; 630 if (status & (MV88E6390_SGMII_INT_LINK_DOWN | 631 MV88E6390_SGMII_INT_LINK_UP)) { 632 ret = IRQ_HANDLED; 633 mv88e6390_serdes_irq_link_sgmii(chip, port->port, lane); 634 } 635 } 636 out: 637 mv88e6xxx_reg_unlock(chip); 638 639 return ret; 640 } 641 642 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) 643 { 644 return irq_find_mapping(chip->g2_irq.domain, port); 645 } 646 647 int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port) 648 { 649 unsigned int irq; 650 int err; 651 u8 lane; 652 653 lane = mv88e6xxx_serdes_get_lane(chip, port); 654 if (!lane) 655 return 0; 656 657 irq = mv88e6xxx_serdes_irq_mapping(chip, port); 658 if (!irq) 659 return 0; 660 661 chip->ports[port].serdes_irq = irq; 662 663 /* Requesting the IRQ will trigger irq callbacks. So we cannot 664 * hold the reg_lock. 665 */ 666 mv88e6xxx_reg_unlock(chip); 667 err = request_threaded_irq(chip->ports[port].serdes_irq, NULL, 668 mv88e6390_serdes_thread_fn, 669 IRQF_ONESHOT, "mv88e6xxx-serdes", 670 &chip->ports[port]); 671 mv88e6xxx_reg_lock(chip); 672 673 if (err) { 674 dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n", 675 err); 676 return err; 677 } 678 679 return mv88e6390_serdes_irq_enable(chip, port, lane); 680 } 681 682 void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port) 683 { 684 u8 lane; 685 686 lane = mv88e6xxx_serdes_get_lane(chip, port); 687 if (!lane) 688 return; 689 690 mv88e6390_serdes_irq_disable(chip, port, lane); 691 692 /* Freeing the IRQ will trigger irq callbacks. So we cannot 693 * hold the reg_lock. 694 */ 695 mv88e6xxx_reg_unlock(chip); 696 free_irq(chip->ports[port].serdes_irq, &chip->ports[port]); 697 mv88e6xxx_reg_lock(chip); 698 699 chip->ports[port].serdes_irq = 0; 700 } 701