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 /* Return the SERDES lane address a port is using. Only Ports 9 and 10 189 * have SERDES lanes. Returns -ENODEV if a port does not have a lane. 190 */ 191 static int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 192 { 193 u8 cmode = chip->ports[port].cmode; 194 195 switch (port) { 196 case 9: 197 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 198 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 199 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 200 return MV88E6390_PORT9_LANE0; 201 return -ENODEV; 202 case 10: 203 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 204 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 205 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 206 return MV88E6390_PORT10_LANE0; 207 return -ENODEV; 208 default: 209 return -ENODEV; 210 } 211 } 212 213 /* Return the SERDES lane address a port is using. Ports 9 and 10 can 214 * use multiple lanes. If so, return the first lane the port uses. 215 * Returns -ENODEV if a port does not have a lane. 216 */ 217 int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 218 { 219 u8 cmode_port9, cmode_port10, cmode_port; 220 221 cmode_port9 = chip->ports[9].cmode; 222 cmode_port10 = chip->ports[10].cmode; 223 cmode_port = chip->ports[port].cmode; 224 225 switch (port) { 226 case 2: 227 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 228 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 229 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 230 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) 231 return MV88E6390_PORT9_LANE1; 232 return -ENODEV; 233 case 3: 234 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 235 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 236 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 237 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 238 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) 239 return MV88E6390_PORT9_LANE2; 240 return -ENODEV; 241 case 4: 242 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 243 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 244 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 245 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 246 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) 247 return MV88E6390_PORT9_LANE3; 248 return -ENODEV; 249 case 5: 250 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 251 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 252 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 253 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) 254 return MV88E6390_PORT10_LANE1; 255 return -ENODEV; 256 case 6: 257 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 258 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 259 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 260 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 261 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) 262 return MV88E6390_PORT10_LANE2; 263 return -ENODEV; 264 case 7: 265 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 266 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 267 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 268 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 269 if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASE_X) 270 return MV88E6390_PORT10_LANE3; 271 return -ENODEV; 272 case 9: 273 if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 274 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII || 275 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 276 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI || 277 cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 278 return MV88E6390_PORT9_LANE0; 279 return -ENODEV; 280 case 10: 281 if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 282 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII || 283 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX || 284 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI || 285 cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI) 286 return MV88E6390_PORT10_LANE0; 287 return -ENODEV; 288 default: 289 return -ENODEV; 290 } 291 } 292 293 /* Set the power on/off for 10GBASE-R and 10GBASE-X4/X2 */ 294 static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane, 295 bool on) 296 { 297 u16 val, new_val; 298 int err; 299 300 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 301 MV88E6390_PCS_CONTROL_1, &val); 302 303 if (err) 304 return err; 305 306 if (on) 307 new_val = val & ~(MV88E6390_PCS_CONTROL_1_RESET | 308 MV88E6390_PCS_CONTROL_1_LOOPBACK | 309 MV88E6390_PCS_CONTROL_1_PDOWN); 310 else 311 new_val = val | MV88E6390_PCS_CONTROL_1_PDOWN; 312 313 if (val != new_val) 314 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 315 MV88E6390_PCS_CONTROL_1, new_val); 316 317 return err; 318 } 319 320 /* Set the power on/off for SGMII and 1000Base-X */ 321 static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane, 322 bool on) 323 { 324 u16 val, new_val; 325 int err; 326 327 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 328 MV88E6390_SGMII_CONTROL, &val); 329 if (err) 330 return err; 331 332 if (on) 333 new_val = val & ~(MV88E6390_SGMII_CONTROL_RESET | 334 MV88E6390_SGMII_CONTROL_LOOPBACK | 335 MV88E6390_SGMII_CONTROL_PDOWN); 336 else 337 new_val = val | MV88E6390_SGMII_CONTROL_PDOWN; 338 339 if (val != new_val) 340 err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 341 MV88E6390_SGMII_CONTROL, new_val); 342 343 return err; 344 } 345 346 static int mv88e6390_serdes_power_lane(struct mv88e6xxx_chip *chip, int port, 347 int lane, bool on) 348 { 349 u8 cmode = chip->ports[port].cmode; 350 351 switch (cmode) { 352 case MV88E6XXX_PORT_STS_CMODE_SGMII: 353 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X: 354 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 355 return mv88e6390_serdes_power_sgmii(chip, lane, on); 356 case MV88E6XXX_PORT_STS_CMODE_XAUI: 357 case MV88E6XXX_PORT_STS_CMODE_RXAUI: 358 return mv88e6390_serdes_power_10g(chip, lane, on); 359 } 360 361 return 0; 362 } 363 364 int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) 365 { 366 int lane; 367 368 lane = mv88e6390_serdes_get_lane(chip, port); 369 if (lane == -ENODEV) 370 return 0; 371 372 if (lane < 0) 373 return lane; 374 375 switch (port) { 376 case 9 ... 10: 377 return mv88e6390_serdes_power_lane(chip, port, lane, on); 378 } 379 380 return 0; 381 } 382 383 int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) 384 { 385 int lane; 386 387 lane = mv88e6390x_serdes_get_lane(chip, port); 388 if (lane == -ENODEV) 389 return 0; 390 391 if (lane < 0) 392 return lane; 393 394 switch (port) { 395 case 2 ... 4: 396 case 5 ... 7: 397 case 9 ... 10: 398 return mv88e6390_serdes_power_lane(chip, port, lane, on); 399 } 400 401 return 0; 402 } 403 404 static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip, 405 int port, int lane) 406 { 407 struct dsa_switch *ds = chip->ds; 408 u16 status; 409 bool up; 410 411 mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 412 MV88E6390_SGMII_STATUS, &status); 413 414 /* Status must be read twice in order to give the current link 415 * status. Otherwise the change in link status since the last 416 * read of the register is returned. 417 */ 418 mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 419 MV88E6390_SGMII_STATUS, &status); 420 up = status & MV88E6390_SGMII_STATUS_LINK; 421 422 dsa_port_phylink_mac_change(ds, port, up); 423 } 424 425 static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip, 426 int lane) 427 { 428 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 429 MV88E6390_SGMII_INT_ENABLE, 430 MV88E6390_SGMII_INT_LINK_DOWN | 431 MV88E6390_SGMII_INT_LINK_UP); 432 } 433 434 static int mv88e6390_serdes_irq_disable_sgmii(struct mv88e6xxx_chip *chip, 435 int lane) 436 { 437 return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 438 MV88E6390_SGMII_INT_ENABLE, 0); 439 } 440 441 int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, 442 int lane) 443 { 444 u8 cmode = chip->ports[port].cmode; 445 int err = 0; 446 447 switch (cmode) { 448 case MV88E6XXX_PORT_STS_CMODE_SGMII: 449 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X: 450 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 451 err = mv88e6390_serdes_irq_enable_sgmii(chip, lane); 452 } 453 454 return err; 455 } 456 457 int mv88e6390_serdes_irq_disable(struct mv88e6xxx_chip *chip, int port, 458 int lane) 459 { 460 u8 cmode = chip->ports[port].cmode; 461 int err = 0; 462 463 switch (cmode) { 464 case MV88E6XXX_PORT_STS_CMODE_SGMII: 465 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X: 466 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 467 err = mv88e6390_serdes_irq_disable_sgmii(chip, lane); 468 } 469 470 return err; 471 } 472 473 static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip, 474 int lane, u16 *status) 475 { 476 int err; 477 478 err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 479 MV88E6390_SGMII_INT_STATUS, status); 480 481 return err; 482 } 483 484 static irqreturn_t mv88e6390_serdes_thread_fn(int irq, void *dev_id) 485 { 486 struct mv88e6xxx_port *port = dev_id; 487 struct mv88e6xxx_chip *chip = port->chip; 488 irqreturn_t ret = IRQ_NONE; 489 u8 cmode = port->cmode; 490 u16 status; 491 int lane; 492 int err; 493 494 lane = mv88e6390x_serdes_get_lane(chip, port->port); 495 496 mutex_lock(&chip->reg_lock); 497 498 switch (cmode) { 499 case MV88E6XXX_PORT_STS_CMODE_SGMII: 500 case MV88E6XXX_PORT_STS_CMODE_1000BASE_X: 501 case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 502 err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status); 503 if (err) 504 goto out; 505 if (status & (MV88E6390_SGMII_INT_LINK_DOWN | 506 MV88E6390_SGMII_INT_LINK_UP)) { 507 ret = IRQ_HANDLED; 508 mv88e6390_serdes_irq_link_sgmii(chip, port->port, lane); 509 } 510 } 511 out: 512 mutex_unlock(&chip->reg_lock); 513 514 return ret; 515 } 516 517 int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port) 518 { 519 int lane; 520 int err; 521 522 /* Only support ports 9 and 10 at the moment */ 523 if (port < 9) 524 return 0; 525 526 lane = mv88e6390x_serdes_get_lane(chip, port); 527 528 if (lane == -ENODEV) 529 return 0; 530 531 if (lane < 0) 532 return lane; 533 534 chip->ports[port].serdes_irq = irq_find_mapping(chip->g2_irq.domain, 535 port); 536 if (chip->ports[port].serdes_irq < 0) { 537 dev_err(chip->dev, "Unable to map SERDES irq: %d\n", 538 chip->ports[port].serdes_irq); 539 return chip->ports[port].serdes_irq; 540 } 541 542 /* Requesting the IRQ will trigger irq callbacks. So we cannot 543 * hold the reg_lock. 544 */ 545 mutex_unlock(&chip->reg_lock); 546 err = request_threaded_irq(chip->ports[port].serdes_irq, NULL, 547 mv88e6390_serdes_thread_fn, 548 IRQF_ONESHOT, "mv88e6xxx-serdes", 549 &chip->ports[port]); 550 mutex_lock(&chip->reg_lock); 551 552 if (err) { 553 dev_err(chip->dev, "Unable to request SERDES interrupt: %d\n", 554 err); 555 return err; 556 } 557 558 return mv88e6390_serdes_irq_enable(chip, port, lane); 559 } 560 561 void mv88e6390_serdes_irq_free(struct mv88e6xxx_chip *chip, int port) 562 { 563 int lane = mv88e6390x_serdes_get_lane(chip, port); 564 565 if (port < 9) 566 return; 567 568 if (lane < 0) 569 return; 570 571 mv88e6390_serdes_irq_disable(chip, port, lane); 572 573 /* Freeing the IRQ will trigger irq callbacks. So we cannot 574 * hold the reg_lock. 575 */ 576 mutex_unlock(&chip->reg_lock); 577 free_irq(chip->ports[port].serdes_irq, &chip->ports[port]); 578 mutex_lock(&chip->reg_lock); 579 580 chip->ports[port].serdes_irq = 0; 581 } 582 583 int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) 584 { 585 u8 cmode = chip->ports[port].cmode; 586 587 if (port != 5) 588 return 0; 589 590 if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || 591 cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || 592 cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) 593 return mv88e6390_serdes_power_sgmii(chip, MV88E6341_ADDR_SERDES, 594 on); 595 596 return 0; 597 } 598