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