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