1 /* 2 * Marvell 88E6xxx SERDES manipulation, via SMI bus 3 * 4 * Copyright (c) 2008 Marvell Semiconductor 5 * 6 * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 */ 13 14 #include <linux/interrupt.h> 15 #include <linux/irqdomain.h> 16 #include <linux/mii.h> 17 18 #include "chip.h" 19 #include "global2.h" 20 #include "phy.h" 21 #include "port.h" 22 #include "serdes.h" 23 24 static int mv88e6352_serdes_read(struct mv88e6xxx_chip *chip, int reg, 25 u16 *val) 26 { 27 return mv88e6xxx_phy_page_read(chip, MV88E6352_ADDR_SERDES, 28 MV88E6352_SERDES_PAGE_FIBER, 29 reg, val); 30 } 31 32 static int mv88e6352_serdes_write(struct mv88e6xxx_chip *chip, int reg, 33 u16 val) 34 { 35 return mv88e6xxx_phy_page_write(chip, MV88E6352_ADDR_SERDES, 36 MV88E6352_SERDES_PAGE_FIBER, 37 reg, val); 38 } 39 40 static int mv88e6390_serdes_read(struct mv88e6xxx_chip *chip, 41 int lane, int device, int reg, u16 *val) 42 { 43 int reg_c45 = MII_ADDR_C45 | device << 16 | reg; 44 45 return mv88e6xxx_phy_read(chip, lane, reg_c45, val); 46 } 47 48 static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip, 49 int lane, int device, int reg, u16 val) 50 { 51 int reg_c45 = MII_ADDR_C45 | device << 16 | reg; 52 53 return mv88e6xxx_phy_write(chip, lane, reg_c45, val); 54 } 55 56 static int mv88e6352_serdes_power_set(struct mv88e6xxx_chip *chip, bool on) 57 { 58 u16 val, new_val; 59 int err; 60 61 err = mv88e6352_serdes_read(chip, MII_BMCR, &val); 62 if (err) 63 return err; 64 65 if (on) 66 new_val = val & ~BMCR_PDOWN; 67 else 68 new_val = val | BMCR_PDOWN; 69 70 if (val != new_val) 71 err = mv88e6352_serdes_write(chip, MII_BMCR, new_val); 72 73 return err; 74 } 75 76 static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port) 77 { 78 u8 cmode = chip->ports[port].cmode; 79 80 if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASE_X) || 81 (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) || 82 (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII)) 83 return true; 84 85 return false; 86 } 87 88 int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) 89 { 90 int err; 91 92 if (mv88e6352_port_has_serdes(chip, port)) { 93 err = mv88e6352_serdes_power_set(chip, on); 94 if (err < 0) 95 return err; 96 } 97 98 return 0; 99 } 100 101 struct mv88e6352_serdes_hw_stat { 102 char string[ETH_GSTRING_LEN]; 103 int sizeof_stat; 104 int reg; 105 }; 106 107 static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = { 108 { "serdes_fibre_rx_error", 16, 21 }, 109 { "serdes_PRBS_error", 32, 24 }, 110 }; 111 112 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port) 113 { 114 if (mv88e6352_port_has_serdes(chip, port)) 115 return ARRAY_SIZE(mv88e6352_serdes_hw_stats); 116 117 return 0; 118 } 119 120 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, 121 int port, uint8_t *data) 122 { 123 struct mv88e6352_serdes_hw_stat *stat; 124 int i; 125 126 if (!mv88e6352_port_has_serdes(chip, port)) 127 return 0; 128 129 for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) { 130 stat = &mv88e6352_serdes_hw_stats[i]; 131 memcpy(data + i * ETH_GSTRING_LEN, stat->string, 132 ETH_GSTRING_LEN); 133 } 134 return ARRAY_SIZE(mv88e6352_serdes_hw_stats); 135 } 136 137 static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip, 138 struct mv88e6352_serdes_hw_stat *stat) 139 { 140 u64 val = 0; 141 u16 reg; 142 int err; 143 144 err = mv88e6352_serdes_read(chip, stat->reg, ®); 145 if (err) { 146 dev_err(chip->dev, "failed to read statistic\n"); 147 return 0; 148 } 149 150 val = reg; 151 152 if (stat->sizeof_stat == 32) { 153 err = mv88e6352_serdes_read(chip, stat->reg + 1, ®); 154 if (err) { 155 dev_err(chip->dev, "failed to read statistic\n"); 156 return 0; 157 } 158 val = val << 16 | reg; 159 } 160 161 return val; 162 } 163 164 int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, 165 uint64_t *data) 166 { 167 struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port]; 168 struct mv88e6352_serdes_hw_stat *stat; 169 u64 value; 170 int i; 171 172 if (!mv88e6352_port_has_serdes(chip, port)) 173 return 0; 174 175 BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) > 176 ARRAY_SIZE(mv88e6xxx_port->serdes_stats)); 177 178 for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) { 179 stat = &mv88e6352_serdes_hw_stats[i]; 180 value = mv88e6352_serdes_get_stat(chip, stat); 181 mv88e6xxx_port->serdes_stats[i] += value; 182 data[i] = mv88e6xxx_port->serdes_stats[i]; 183 } 184 185 return ARRAY_SIZE(mv88e6352_serdes_hw_stats); 186 } 187 188 static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port) 189 { 190 struct dsa_switch *ds = chip->ds; 191 u16 status; 192 bool up; 193 194 mv88e6352_serdes_read(chip, MII_BMSR, &status); 195 196 /* Status must be read twice in order to give the current link 197 * status. Otherwise the change in link status since the last 198 * read of the register is returned. 199 */ 200 mv88e6352_serdes_read(chip, MII_BMSR, &status); 201 202 up = status & BMSR_LSTATUS; 203 204 dsa_port_phylink_mac_change(ds, port, up); 205 } 206 207 static irqreturn_t mv88e6352_serdes_thread_fn(int irq, void *dev_id) 208 { 209 struct mv88e6xxx_port *port = dev_id; 210 struct mv88e6xxx_chip *chip = port->chip; 211 irqreturn_t ret = IRQ_NONE; 212 u16 status; 213 int err; 214 215 mutex_lock(&chip->reg_lock); 216 217 err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status); 218 if (err) 219 goto out; 220 221 if (status & MV88E6352_SERDES_INT_LINK_CHANGE) { 222 ret = IRQ_HANDLED; 223 mv88e6352_serdes_irq_link(chip, port->port); 224 } 225 out: 226 mutex_unlock(&chip->reg_lock); 227 228 return ret; 229 } 230 231 static int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip) 232 { 233 return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, 234 MV88E6352_SERDES_INT_LINK_CHANGE); 235 } 236 237 static int mv88e6352_serdes_irq_disable(struct mv88e6xxx_chip *chip) 238 { 239 return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, 0); 240 } 241 242 int mv88e6352_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port) 243 { 244 int err; 245 246 if (!mv88e6352_port_has_serdes(chip, port)) 247 return 0; 248 249 chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain, 250 MV88E6352_SERDES_IRQ); 251 if (chip->ports[port].serdes_irq < 0) { 252 dev_err(chip->dev, "Unable to map SERDES irq: %d\n", 253 chip->ports[port].serdes_irq); 254 return chip->ports[port].serdes_irq; 255 } 256 257 /* Requesting the IRQ will trigger irq callbacks. So we cannot 258 * hold the reg_lock. 259 */ 260 mutex_unlock(&chip->reg_lock); 261 err = request_threaded_irq(chip->ports[port].serdes_irq, NULL, 262 mv88e6352_serdes_thread_fn, 263 IRQF_ONESHOT, "mv88e6xxx-serdes", 264 &chip->ports[port]); 265 mutex_lock(&chip->reg_lock); 266 267 if (err) { 268 dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n", 269 err); 270 return err; 271 } 272 273 return mv88e6352_serdes_irq_enable(chip); 274 } 275 276 void mv88e6352_serdes_irq_free(struct mv88e6xxx_chip *chip, int port) 277 { 278 if (!mv88e6352_port_has_serdes(chip, port)) 279 return; 280 281 mv88e6352_serdes_irq_disable(chip); 282 283 /* Freeing the IRQ will trigger irq callbacks. So we cannot 284 * hold the reg_lock. 285 */ 286 mutex_unlock(&chip->reg_lock); 287 free_irq(chip->ports[port].serdes_irq, &chip->ports[port]); 288 mutex_lock(&chip->reg_lock); 289 290 chip->ports[port].serdes_irq = 0; 291 } 292 293 /* Return the SERDES lane address a port is using. Only Ports 9 and 10 294 * have SERDES lanes. Returns -ENODEV if a port does not have a lane. 295 */ 296 static int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 297 { 298 u8 cmode = chip->ports[port].cmode; 299 300 switch (port) { 301 case 9: 302 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 303 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 304 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 305 return MV88E6390_PORT9_LANE0; 306 return -ENODEV; 307 case 10: 308 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 309 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 310 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 311 return MV88E6390_PORT10_LANE0; 312 return -ENODEV; 313 default: 314 return -ENODEV; 315 } 316 } 317 318 /* Return the SERDES lane address a port is using. Ports 9 and 10 can 319 * use multiple lanes. If so, return the first lane the port uses. 320 * Returns -ENODEV if a port does not have a lane. 321 */ 322 int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 323 { 324 u8 cmode_port9, cmode_port10, cmode_port; 325 326 cmode_port9 = chip->ports[9].cmode; 327 cmode_port10 = chip->ports[10].cmode; 328 cmode_port = chip->ports[port].cmode; 329 330 switch (port) { 331 case 2: 332 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 333 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 334 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 335 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) 336 return MV88E6390_PORT9_LANE1; 337 return -ENODEV; 338 case 3: 339 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 340 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 341 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 342 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 343 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) 344 return MV88E6390_PORT9_LANE2; 345 return -ENODEV; 346 case 4: 347 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 348 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 349 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 350 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 351 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) 352 return MV88E6390_PORT9_LANE3; 353 return -ENODEV; 354 case 5: 355 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 356 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 357 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 358 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) 359 return MV88E6390_PORT10_LANE1; 360 return -ENODEV; 361 case 6: 362 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 363 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 364 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 365 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 366 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) 367 return MV88E6390_PORT10_LANE2; 368 return -ENODEV; 369 case 7: 370 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 371 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 372 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 373 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 374 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) 375 return MV88E6390_PORT10_LANE3; 376 return -ENODEV; 377 case 9: 378 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 379 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 380 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 381 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI || 382 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 383 return MV88E6390_PORT9_LANE0; 384 return -ENODEV; 385 case 10: 386 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 387 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 388 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 389 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI || 390 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 391 return MV88E6390_PORT10_LANE0; 392 return -ENODEV; 393 default: 394 return -ENODEV; 395 } 396 } 397 398 /* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */ 399 static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane, 400 bool on) 401 { 402 u16 val, new_val; 403 int err; 404 405 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 406 MV88E6390_PCS_CONTROL_1, &val); 407 408 if (err) 409 return err; 410 411 if (on) 412 new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET | 413 MV88E6390_PCS_CONTROL_1_LOOPBACK | 414 MV88E6390_PCS_CONTROL_1_PDOWN); 415 else 416 new_val = val | MV88E6390_PCS_CONTROL_1_PDOWN; 417 418 if (val != new_val) 419 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 420 MV88E6390_PCS_CONTROL_1, new_val); 421 422 return err; 423 } 424 425 /* Set the power on/off for SGMII and 1000Base-X */ 426 static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane, 427 bool on) 428 { 429 u16 val, new_val; 430 int err; 431 432 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 433 MV88E6390_SGMII_CONTROL, &val); 434 if (err) 435 return err; 436 437 if (on) 438 new_val = val & ~(MV88E6390_SGMII_CONTROL_RESET | 439 MV88E6390_SGMII_CONTROL_LOOPBACK | 440 MV88E6390_SGMII_CONTROL_PDOWN); 441 else 442 new_val = val | MV88E6390_SGMII_CONTROL_PDOWN; 443 444 if (val != new_val) 445 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 446 MV88E6390_SGMII_CONTROL, new_val); 447 448 return err; 449 } 450 451 static int mv88e6390_serdes_power_lane(struct mv88e6xxx_chip *chip, int port, 452 int lane, bool on) 453 { 454 u8 cmode = chip->ports[port].cmode; 455 456 switch (cmode) { 457 case MV88E6XXX_PORT_STS_CMODE_SGMII: 458 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X: 459 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 460 return mv88e6390_serdes_power_sgmii(chip, lane, on); 461 case MV88E6XXX_PORT_STS_CMODE_XAUI: 462 case MV88E6XXX_PORT_STS_CMODE_RXAUI: 463 return mv88e6390_serdes_power_10g(chip, lane, on); 464 } 465 466 return 0; 467 } 468 469 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) 470 { 471 int lane; 472 473 lane = mv88e6390_serdes_get_lane(chip, port); 474 if (lane == -ENODEV) 475 return 0; 476 477 if (lane < 0) 478 return lane; 479 480 switch (port) { 481 case 9 ... 10: 482 return mv88e6390_serdes_power_lane(chip, port, lane, on); 483 } 484 485 return 0; 486 } 487 488 int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) 489 { 490 int lane; 491 492 lane = mv88e6390x_serdes_get_lane(chip, port); 493 if (lane == -ENODEV) 494 return 0; 495 496 if (lane < 0) 497 return lane; 498 499 switch (port) { 500 case 2 ... 4: 501 case 5 ... 7: 502 case 9 ... 10: 503 return mv88e6390_serdes_power_lane(chip, port, lane, on); 504 } 505 506 return 0; 507 } 508 509 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip, 510 int port, int lane) 511 { 512 struct dsa_switch *ds = chip->ds; 513 int duplex = DUPLEX_UNKNOWN; 514 int speed = SPEED_UNKNOWN; 515 int link, err; 516 u16 status; 517 518 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 519 MV88E6390_SGMII_PHY_STATUS, &status); 520 if (err) { 521 dev_err(chip->dev, "can't read SGMII PHY status: %d\n", err); 522 return; 523 } 524 525 link = status & MV88E6390_SGMII_PHY_STATUS_LINK ? 526 LINK_FORCED_UP : LINK_FORCED_DOWN; 527 528 if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) { 529 duplex = status & MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ? 530 DUPLEX_FULL : DUPLEX_HALF; 531 532 switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) { 533 case MV88E6390_SGMII_PHY_STATUS_SPEED_1000: 534 speed = SPEED_1000; 535 break; 536 case MV88E6390_SGMII_PHY_STATUS_SPEED_100: 537 speed = SPEED_100; 538 break; 539 case MV88E6390_SGMII_PHY_STATUS_SPEED_10: 540 speed = SPEED_10; 541 break; 542 default: 543 dev_err(chip->dev, "invalid PHY speed\n"); 544 return; 545 } 546 } 547 548 err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex, 549 PAUSE_OFF, PHY_INTERFACE_MODE_NA); 550 if (err) 551 dev_err(chip->dev, "can't propagate PHY settings to MAC: %d\n", 552 err); 553 else 554 dsa_port_phylink_mac_change(ds, port, link == LINK_FORCED_UP); 555 } 556 557 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip, 558 int lane) 559 { 560 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 561 MV88E6390_SGMII_INT_ENABLE, 562 MV88E6390_SGMII_INT_LINK_DOWN | 563 MV88E6390_SGMII_INT_LINK_UP); 564 } 565 566 static int mv88e6390_serdes_irq_disable_sgmii(struct mv88e6xxx_chip *chip, 567 int lane) 568 { 569 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 570 MV88E6390_SGMII_INT_ENABLE, 0); 571 } 572 573 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, 574 int lane) 575 { 576 u8 cmode = chip->ports[port].cmode; 577 int err = 0; 578 579 switch (cmode) { 580 case MV88E6XXX_PORT_STS_CMODE_SGMII: 581 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X: 582 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 583 err = mv88e6390_serdes_irq_enable_sgmii(chip, lane); 584 } 585 586 return err; 587 } 588 589 int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port, 590 int lane) 591 { 592 u8 cmode = chip->ports[port].cmode; 593 int err = 0; 594 595 switch (cmode) { 596 case MV88E6XXX_PORT_STS_CMODE_SGMII: 597 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X: 598 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 599 err = mv88e6390_serdes_irq_disable_sgmii(chip, lane); 600 } 601 602 return err; 603 } 604 605 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip, 606 int lane, u16 *status) 607 { 608 int err; 609 610 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 611 MV88E6390_SGMII_INT_STATUS, status); 612 613 return err; 614 } 615 616 static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id) 617 { 618 struct mv88e6xxx_port *port = dev_id; 619 struct mv88e6xxx_chip *chip = port->chip; 620 irqreturn_t ret = IRQ_NONE; 621 u8 cmode = port->cmode; 622 u16 status; 623 int lane; 624 int err; 625 626 lane = mv88e6390x_serdes_get_lane(chip, port->port); 627 628 mutex_lock(&chip->reg_lock); 629 630 switch (cmode) { 631 case MV88E6XXX_PORT_STS_CMODE_SGMII: 632 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X: 633 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 634 err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status); 635 if (err) 636 goto out; 637 if (status & (MV88E6390_SGMII_INT_LINK_DOWN | 638 MV88E6390_SGMII_INT_LINK_UP)) { 639 ret = IRQ_HANDLED; 640 mv88e6390_serdes_irq_link_sgmii(chip, port->port, lane); 641 } 642 } 643 out: 644 mutex_unlock(&chip->reg_lock); 645 646 return ret; 647 } 648 649 int mv88e6390x_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port) 650 { 651 int lane; 652 int err; 653 654 lane = mv88e6390x_serdes_get_lane(chip, port); 655 656 if (lane == -ENODEV) 657 return 0; 658 659 if (lane < 0) 660 return lane; 661 662 chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain, 663 port); 664 if (chip->ports[port].serdes_irq < 0) { 665 dev_err(chip->dev, "Unable to map SERDES irq: %d\n", 666 chip->ports[port].serdes_irq); 667 return chip->ports[port].serdes_irq; 668 } 669 670 /* Requesting the IRQ will trigger irq callbacks. So we cannot 671 * hold the reg_lock. 672 */ 673 mutex_unlock(&chip->reg_lock); 674 err = request_threaded_irq(chip->ports[port].serdes_irq, NULL, 675 mv88e6390_serdes_thread_fn, 676 IRQF_ONESHOT, "mv88e6xxx-serdes", 677 &chip->ports[port]); 678 mutex_lock(&chip->reg_lock); 679 680 if (err) { 681 dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n", 682 err); 683 return err; 684 } 685 686 return mv88e6390_serdes_irq_enable(chip, port, lane); 687 } 688 689 int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port) 690 { 691 if (port < 9) 692 return 0; 693 694 return mv88e6390x_serdes_irq_setup(chip, port); 695 } 696 697 void mv88e6390x_serdes_irq_free(struct mv88e6xxx_chip *chip, int port) 698 { 699 int lane = mv88e6390x_serdes_get_lane(chip, port); 700 701 if (lane == -ENODEV) 702 return; 703 704 if (lane < 0) 705 return; 706 707 mv88e6390_serdes_irq_disable(chip, port, lane); 708 709 /* Freeing the IRQ will trigger irq callbacks. So we cannot 710 * hold the reg_lock. 711 */ 712 mutex_unlock(&chip->reg_lock); 713 free_irq(chip->ports[port].serdes_irq, &chip->ports[port]); 714 mutex_lock(&chip->reg_lock); 715 716 chip->ports[port].serdes_irq = 0; 717 } 718 719 void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port) 720 { 721 if (port < 9) 722 return; 723 724 mv88e6390x_serdes_irq_free(chip, port); 725 } 726 727 int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) 728 { 729 u8 cmode = chip->ports[port].cmode; 730 731 if (port != 5) 732 return 0; 733 734 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 735 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 736 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 737 return mv88e6390_serdes_power_sgmii(chip, MV88E6341_ADDR_SERDES, 738 on); 739 740 return 0; 741 } 742