Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

phy: lynx-28g: refactor lane->interface to lane->mode

Lynx 28G is a multi-protocol SerDes - it handles serial Ethernet, PCIe,
SATA.

The driver should not use the phylib-specific phy_interface_t as an
internal data representation, but something specific to its internal
capabilities, and only convert to phy_interface_t when PHY_MODE_ETHERNET
is selected and used.

Otherwise it has no way of representing the non-Ethernet lanes (which
was not a short-term goal when the driver was introduced, and is not a
goal per se right now either, but should nonetheless be possible).

Prefer the "enum lynx_lane_mode" name over "lynx_28g_lane_mode", in
preparation of future Lynx 10G SerDes support. This SerDes is part of
the same IP family and has similar capabilities, and will reuse some
code, hence the common data type.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Link: https://patch.msgid.link/20251125114847.804961-12-vladimir.oltean@nxp.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Vladimir Oltean and committed by
Vinod Koul
6a1ae518 444bb9a7

+106 -102
+106 -102
drivers/phy/freescale/phy-fsl-lynx-28g.c
··· 243 243 PROTO_SEL_25G_50G_100G = 0x1a, 244 244 }; 245 245 246 + enum lynx_lane_mode { 247 + LANE_MODE_UNKNOWN, 248 + LANE_MODE_1000BASEX_SGMII, 249 + LANE_MODE_10GBASER_USXGMII, 250 + LANE_MODE_MAX, 251 + }; 252 + 246 253 struct lynx_28g_proto_conf { 247 254 /* LNaGCR0 */ 248 255 int proto_sel; ··· 287 280 int smp_autoz_eg1r; 288 281 }; 289 282 290 - static const struct lynx_28g_proto_conf lynx_28g_proto_conf[PHY_INTERFACE_MODE_MAX] = { 291 - [PHY_INTERFACE_MODE_SGMII] = { 283 + static const struct lynx_28g_proto_conf lynx_28g_proto_conf[LANE_MODE_MAX] = { 284 + [LANE_MODE_1000BASEX_SGMII] = { 292 285 .proto_sel = LNaGCR0_PROTO_SEL_SGMII, 293 286 .if_width = LNaGCR0_IF_WIDTH_10_BIT, 294 287 .teq_type = EQ_TYPE_NO_EQ, ··· 316 309 .smp_autoz_d1r = 0, 317 310 .smp_autoz_eg1r = 0, 318 311 }, 319 - [PHY_INTERFACE_MODE_1000BASEX] = { 320 - .proto_sel = LNaGCR0_PROTO_SEL_SGMII, 321 - .if_width = LNaGCR0_IF_WIDTH_10_BIT, 322 - .teq_type = EQ_TYPE_NO_EQ, 323 - .sgn_preq = 1, 324 - .ratio_preq = 0, 325 - .sgn_post1q = 1, 326 - .ratio_post1q = 0, 327 - .amp_red = 6, 328 - .adpt_eq = 48, 329 - .enter_idle_flt_sel = 4, 330 - .exit_idle_flt_sel = 3, 331 - .data_lost_th_sel = 1, 332 - .gk2ovd = 0x1f, 333 - .gk3ovd = 0, 334 - .gk4ovd = 0, 335 - .gk2ovd_en = 1, 336 - .gk3ovd_en = 1, 337 - .gk4ovd_en = 0, 338 - .eq_offset_ovd = 0x1f, 339 - .eq_offset_ovd_en = 0, 340 - .eq_offset_rng_dbl = 0, 341 - .eq_blw_sel = 0, 342 - .eq_boost = 0, 343 - .spare_in = 0, 344 - .smp_autoz_d1r = 0, 345 - .smp_autoz_eg1r = 0, 346 - }, 347 - [PHY_INTERFACE_MODE_10GBASER] = { 312 + [LANE_MODE_10GBASER_USXGMII] = { 348 313 .proto_sel = LNaGCR0_PROTO_SEL_XFI, 349 314 .if_width = LNaGCR0_IF_WIDTH_20_BIT, 350 315 .teq_type = EQ_TYPE_2TAP, ··· 358 379 struct lynx_28g_priv *priv; 359 380 u32 rstctl, cr0, cr1; 360 381 int id; 361 - DECLARE_PHY_INTERFACE_MASK(supported); 382 + DECLARE_BITMAP(supported, LANE_MODE_MAX); 362 383 }; 363 384 364 385 struct lynx_28g_lane { ··· 367 388 bool powered_up; 368 389 bool init; 369 390 unsigned int id; 370 - phy_interface_t interface; 391 + enum lynx_lane_mode mode; 371 392 }; 372 393 373 394 struct lynx_28g_priv { ··· 408 429 #define lynx_28g_pll_read(pll, reg) \ 409 430 ioread32((pll)->priv->base + reg((pll)->id)) 410 431 411 - static bool lynx_28g_supports_interface(struct lynx_28g_priv *priv, int intf) 432 + static const char *lynx_lane_mode_str(enum lynx_lane_mode lane_mode) 433 + { 434 + switch (lane_mode) { 435 + case LANE_MODE_1000BASEX_SGMII: 436 + return "1000Base-X/SGMII"; 437 + case LANE_MODE_10GBASER_USXGMII: 438 + return "10GBase-R/USXGMII"; 439 + default: 440 + return "unknown"; 441 + } 442 + } 443 + 444 + static enum lynx_lane_mode phy_interface_to_lane_mode(phy_interface_t intf) 445 + { 446 + switch (intf) { 447 + case PHY_INTERFACE_MODE_SGMII: 448 + case PHY_INTERFACE_MODE_1000BASEX: 449 + return LANE_MODE_1000BASEX_SGMII; 450 + case PHY_INTERFACE_MODE_10GBASER: 451 + case PHY_INTERFACE_MODE_USXGMII: 452 + return LANE_MODE_10GBASER_USXGMII; 453 + default: 454 + return LANE_MODE_UNKNOWN; 455 + } 456 + } 457 + 458 + static bool lynx_28g_supports_lane_mode(struct lynx_28g_priv *priv, 459 + enum lynx_lane_mode mode) 412 460 { 413 461 int i; 414 462 ··· 443 437 if (PLLnRSTCTL_DIS(priv->pll[i].rstctl)) 444 438 continue; 445 439 446 - if (test_bit(intf, priv->pll[i].supported)) 440 + if (test_bit(mode, priv->pll[i].supported)) 447 441 return true; 448 442 } 449 443 ··· 451 445 } 452 446 453 447 static struct lynx_28g_pll *lynx_28g_pll_get(struct lynx_28g_priv *priv, 454 - phy_interface_t intf) 448 + enum lynx_lane_mode mode) 455 449 { 456 450 struct lynx_28g_pll *pll; 457 451 int i; ··· 462 456 if (PLLnRSTCTL_DIS(pll->rstctl)) 463 457 continue; 464 458 465 - if (test_bit(intf, pll->supported)) 459 + if (test_bit(mode, pll->supported)) 466 460 return pll; 467 461 } 468 462 469 463 /* no pll supports requested mode, either caller forgot to check 470 464 * lynx_28g_supports_lane_mode, or this is a bug. 471 465 */ 472 - dev_WARN_ONCE(priv->dev, 1, "no pll for interface %s\n", phy_modes(intf)); 466 + dev_WARN_ONCE(priv->dev, 1, "no pll for lane mode %s\n", 467 + lynx_lane_mode_str(mode)); 473 468 return NULL; 474 469 } 475 470 476 471 static void lynx_28g_lane_set_nrate(struct lynx_28g_lane *lane, 477 472 struct lynx_28g_pll *pll, 478 - phy_interface_t intf) 473 + enum lynx_lane_mode lane_mode) 479 474 { 480 475 switch (FIELD_GET(PLLnCR1_FRATE_SEL, pll->cr1)) { 481 476 case PLLnCR1_FRATE_5G_10GVCO: 482 477 case PLLnCR1_FRATE_5G_25GVCO: 483 - switch (intf) { 484 - case PHY_INTERFACE_MODE_SGMII: 485 - case PHY_INTERFACE_MODE_1000BASEX: 478 + switch (lane_mode) { 479 + case LANE_MODE_1000BASEX_SGMII: 486 480 lynx_28g_lane_rmw(lane, LNaTGCR0, 487 481 FIELD_PREP(LNaTGCR0_N_RATE, LNaTGCR0_N_RATE_QUARTER), 488 482 LNaTGCR0_N_RATE); ··· 495 489 } 496 490 break; 497 491 case PLLnCR1_FRATE_10G_20GVCO: 498 - switch (intf) { 499 - case PHY_INTERFACE_MODE_10GBASER: 500 - case PHY_INTERFACE_MODE_USXGMII: 492 + switch (lane_mode) { 493 + case LANE_MODE_10GBASER_USXGMII: 501 494 lynx_28g_lane_rmw(lane, LNaTGCR0, 502 495 FIELD_PREP(LNaTGCR0_N_RATE, LNaTGCR0_N_RATE_FULL), 503 496 LNaTGCR0_N_RATE); ··· 585 580 return 0; 586 581 } 587 582 588 - static int lynx_28g_get_pccr(phy_interface_t interface, int lane, 583 + static int lynx_28g_get_pccr(enum lynx_lane_mode lane_mode, int lane, 589 584 struct lynx_pccr *pccr) 590 585 { 591 - switch (interface) { 592 - case PHY_INTERFACE_MODE_SGMII: 593 - case PHY_INTERFACE_MODE_1000BASEX: 586 + switch (lane_mode) { 587 + case LANE_MODE_1000BASEX_SGMII: 594 588 pccr->offset = PCC8; 595 589 pccr->width = 4; 596 590 pccr->shift = SGMII_CFG(lane); 597 591 break; 598 - case PHY_INTERFACE_MODE_10GBASER: 592 + case LANE_MODE_10GBASER_USXGMII: 599 593 pccr->offset = PCCC; 600 594 pccr->width = 4; 601 595 pccr->shift = SXGMII_CFG(lane); ··· 606 602 return 0; 607 603 } 608 604 609 - static int lynx_28g_get_pcvt_offset(int lane, phy_interface_t interface) 605 + static int lynx_28g_get_pcvt_offset(int lane, enum lynx_lane_mode lane_mode) 610 606 { 611 - switch (interface) { 612 - case PHY_INTERFACE_MODE_SGMII: 613 - case PHY_INTERFACE_MODE_1000BASEX: 607 + switch (lane_mode) { 608 + case LANE_MODE_1000BASEX_SGMII: 614 609 return SGMIIaCR0(lane); 615 - case PHY_INTERFACE_MODE_10GBASER: 610 + case LANE_MODE_10GBASER_USXGMII: 616 611 return SXGMIIaCR0(lane); 617 612 default: 618 613 return -EOPNOTSUPP; ··· 619 616 } 620 617 621 618 static int lynx_pccr_write(struct lynx_28g_lane *lane, 622 - phy_interface_t interface, u32 val) 619 + enum lynx_lane_mode lane_mode, u32 val) 623 620 { 624 621 struct lynx_28g_priv *priv = lane->priv; 625 622 struct lynx_pccr pccr; 626 623 u32 old, tmp, mask; 627 624 int err; 628 625 629 - err = lynx_28g_get_pccr(interface, lane->id, &pccr); 626 + err = lynx_28g_get_pccr(lane_mode, lane->id, &pccr); 630 627 if (err) 631 628 return err; 632 629 ··· 641 638 return 0; 642 639 } 643 640 644 - static int lynx_pcvt_read(struct lynx_28g_lane *lane, phy_interface_t interface, 645 - int cr, u32 *val) 641 + static int lynx_pcvt_read(struct lynx_28g_lane *lane, 642 + enum lynx_lane_mode lane_mode, int cr, u32 *val) 646 643 { 647 644 struct lynx_28g_priv *priv = lane->priv; 648 645 int offset; 649 646 650 - offset = lynx_28g_get_pcvt_offset(lane->id, interface); 647 + offset = lynx_28g_get_pcvt_offset(lane->id, lane_mode); 651 648 if (offset < 0) 652 649 return offset; 653 650 ··· 656 653 return 0; 657 654 } 658 655 659 - static int lynx_pcvt_write(struct lynx_28g_lane *lane, phy_interface_t interface, 660 - int cr, u32 val) 656 + static int lynx_pcvt_write(struct lynx_28g_lane *lane, 657 + enum lynx_lane_mode lane_mode, int cr, u32 val) 661 658 { 662 659 struct lynx_28g_priv *priv = lane->priv; 663 660 int offset; 664 661 665 - offset = lynx_28g_get_pcvt_offset(lane->id, interface); 662 + offset = lynx_28g_get_pcvt_offset(lane->id, lane_mode); 666 663 if (offset < 0) 667 664 return offset; 668 665 ··· 671 668 return 0; 672 669 } 673 670 674 - static int lynx_pcvt_rmw(struct lynx_28g_lane *lane, phy_interface_t interface, 671 + static int lynx_pcvt_rmw(struct lynx_28g_lane *lane, 672 + enum lynx_lane_mode lane_mode, 675 673 int cr, u32 val, u32 mask) 676 674 { 677 675 int err; 678 676 u32 tmp; 679 677 680 - err = lynx_pcvt_read(lane, interface, cr, &tmp); 678 + err = lynx_pcvt_read(lane, lane_mode, cr, &tmp); 681 679 if (err) 682 680 return err; 683 681 684 682 tmp &= ~mask; 685 683 tmp |= val; 686 684 687 - return lynx_pcvt_write(lane, interface, cr, tmp); 685 + return lynx_pcvt_write(lane, lane_mode, cr, tmp); 688 686 } 689 687 690 688 static void lynx_28g_lane_remap_pll(struct lynx_28g_lane *lane, 691 - phy_interface_t interface) 689 + enum lynx_lane_mode lane_mode) 692 690 { 693 691 struct lynx_28g_priv *priv = lane->priv; 694 692 struct lynx_28g_pll *pll; 695 693 696 694 /* Switch to the PLL that works with this interface type */ 697 - pll = lynx_28g_pll_get(priv, interface); 695 + pll = lynx_28g_pll_get(priv, lane_mode); 698 696 if (unlikely(pll == NULL)) 699 697 return; 700 698 701 699 lynx_28g_lane_set_pll(lane, pll); 702 700 703 701 /* Choose the portion of clock net to be used on this lane */ 704 - lynx_28g_lane_set_nrate(lane, pll, interface); 702 + lynx_28g_lane_set_nrate(lane, pll, lane_mode); 705 703 } 706 704 707 705 static void lynx_28g_lane_change_proto_conf(struct lynx_28g_lane *lane, 708 - phy_interface_t interface) 706 + enum lynx_lane_mode lane_mode) 709 707 { 710 - const struct lynx_28g_proto_conf *conf = &lynx_28g_proto_conf[interface]; 708 + const struct lynx_28g_proto_conf *conf = &lynx_28g_proto_conf[lane_mode]; 711 709 712 710 lynx_28g_lane_rmw(lane, LNaGCR0, 713 711 FIELD_PREP(LNaGCR0_PROTO_SEL, conf->proto_sel) | ··· 779 775 } 780 776 781 777 static int lynx_28g_lane_disable_pcvt(struct lynx_28g_lane *lane, 782 - phy_interface_t interface) 778 + enum lynx_lane_mode lane_mode) 783 779 { 784 780 struct lynx_28g_priv *priv = lane->priv; 785 781 int err; 786 782 787 783 spin_lock(&priv->pcc_lock); 788 784 789 - err = lynx_pccr_write(lane, interface, 0); 785 + err = lynx_pccr_write(lane, lane_mode, 0); 790 786 if (err) 791 787 goto out; 792 788 793 - switch (interface) { 794 - case PHY_INTERFACE_MODE_SGMII: 795 - case PHY_INTERFACE_MODE_1000BASEX: 796 - err = lynx_pcvt_rmw(lane, interface, CR(1), 0, 789 + switch (lane_mode) { 790 + case LANE_MODE_1000BASEX_SGMII: 791 + err = lynx_pcvt_rmw(lane, lane_mode, CR(1), 0, 797 792 SGMIIaCR1_SGPCS_EN); 798 793 break; 799 794 default: ··· 806 803 } 807 804 808 805 static int lynx_28g_lane_enable_pcvt(struct lynx_28g_lane *lane, 809 - phy_interface_t interface) 806 + enum lynx_lane_mode lane_mode) 810 807 { 811 808 struct lynx_28g_priv *priv = lane->priv; 812 809 u32 val; ··· 814 811 815 812 spin_lock(&priv->pcc_lock); 816 813 817 - switch (interface) { 818 - case PHY_INTERFACE_MODE_SGMII: 819 - case PHY_INTERFACE_MODE_1000BASEX: 820 - err = lynx_pcvt_rmw(lane, interface, CR(1), SGMIIaCR1_SGPCS_EN, 814 + switch (lane_mode) { 815 + case LANE_MODE_1000BASEX_SGMII: 816 + err = lynx_pcvt_rmw(lane, lane_mode, CR(1), SGMIIaCR1_SGPCS_EN, 821 817 SGMIIaCR1_SGPCS_EN); 822 818 break; 823 819 default: ··· 825 823 826 824 val = 0; 827 825 828 - switch (interface) { 829 - case PHY_INTERFACE_MODE_SGMII: 830 - case PHY_INTERFACE_MODE_1000BASEX: 826 + switch (lane_mode) { 827 + case LANE_MODE_1000BASEX_SGMII: 831 828 val |= PCC8_SGMIIa_CFG; 832 829 break; 833 - case PHY_INTERFACE_MODE_10GBASER: 830 + case LANE_MODE_10GBASER_USXGMII: 834 831 val |= PCCC_SXGMIIn_CFG | PCCC_SXGMIIn_XFI; 835 832 break; 836 833 default: 837 834 break; 838 835 } 839 836 840 - err = lynx_pccr_write(lane, interface, val); 837 + err = lynx_pccr_write(lane, lane_mode, val); 841 838 842 839 spin_unlock(&priv->pcc_lock); 843 840 ··· 848 847 struct lynx_28g_lane *lane = phy_get_drvdata(phy); 849 848 struct lynx_28g_priv *priv = lane->priv; 850 849 int powered_up = lane->powered_up; 850 + enum lynx_lane_mode lane_mode; 851 851 int err = 0; 852 852 853 853 if (mode != PHY_MODE_ETHERNET) 854 854 return -EOPNOTSUPP; 855 855 856 - if (lane->interface == PHY_INTERFACE_MODE_NA) 856 + if (lane->mode == LANE_MODE_UNKNOWN) 857 857 return -EOPNOTSUPP; 858 858 859 - if (!lynx_28g_supports_interface(priv, submode)) 859 + lane_mode = phy_interface_to_lane_mode(submode); 860 + if (!lynx_28g_supports_lane_mode(priv, lane_mode)) 860 861 return -EOPNOTSUPP; 861 862 862 - if (submode == lane->interface) 863 + if (lane_mode == lane->mode) 863 864 return 0; 864 865 865 866 /* If the lane is powered up, put the lane into the halt state while ··· 870 867 if (powered_up) 871 868 lynx_28g_power_off(phy); 872 869 873 - err = lynx_28g_lane_disable_pcvt(lane, lane->interface); 870 + err = lynx_28g_lane_disable_pcvt(lane, lane->mode); 874 871 if (err) 875 872 goto out; 876 873 877 - lynx_28g_lane_change_proto_conf(lane, submode); 878 - lynx_28g_lane_remap_pll(lane, submode); 879 - WARN_ON(lynx_28g_lane_enable_pcvt(lane, submode)); 874 + lynx_28g_lane_change_proto_conf(lane, lane_mode); 875 + lynx_28g_lane_remap_pll(lane, lane_mode); 876 + WARN_ON(lynx_28g_lane_enable_pcvt(lane, lane_mode)); 880 877 881 - lane->interface = submode; 878 + lane->mode = lane_mode; 882 879 883 880 out: 884 881 if (powered_up) ··· 892 889 { 893 890 struct lynx_28g_lane *lane = phy_get_drvdata(phy); 894 891 struct lynx_28g_priv *priv = lane->priv; 892 + enum lynx_lane_mode lane_mode; 895 893 896 894 if (mode != PHY_MODE_ETHERNET) 897 895 return -EOPNOTSUPP; 898 896 899 - if (!lynx_28g_supports_interface(priv, submode)) 897 + lane_mode = phy_interface_to_lane_mode(submode); 898 + if (!lynx_28g_supports_lane_mode(priv, lane_mode)) 900 899 return -EOPNOTSUPP; 901 900 902 901 return 0; ··· 951 946 case PLLnCR1_FRATE_5G_10GVCO: 952 947 case PLLnCR1_FRATE_5G_25GVCO: 953 948 /* 5GHz clock net */ 954 - __set_bit(PHY_INTERFACE_MODE_1000BASEX, pll->supported); 955 - __set_bit(PHY_INTERFACE_MODE_SGMII, pll->supported); 949 + __set_bit(LANE_MODE_1000BASEX_SGMII, pll->supported); 956 950 break; 957 951 case PLLnCR1_FRATE_10G_20GVCO: 958 952 /* 10.3125GHz clock net */ 959 - __set_bit(PHY_INTERFACE_MODE_10GBASER, pll->supported); 953 + __set_bit(LANE_MODE_10GBASER_USXGMII, pll->supported); 960 954 break; 961 955 default: 962 956 /* 6GHz, 12.890625GHz, 8GHz */ ··· 1006 1002 protocol = FIELD_GET(LNaPSS_TYPE, pss); 1007 1003 switch (protocol) { 1008 1004 case LNaPSS_TYPE_SGMII: 1009 - lane->interface = PHY_INTERFACE_MODE_SGMII; 1005 + lane->mode = LANE_MODE_1000BASEX_SGMII; 1010 1006 break; 1011 1007 case LNaPSS_TYPE_XFI: 1012 - lane->interface = PHY_INTERFACE_MODE_10GBASER; 1008 + lane->mode = LANE_MODE_10GBASER_USXGMII; 1013 1009 break; 1014 1010 default: 1015 - lane->interface = PHY_INTERFACE_MODE_NA; 1011 + lane->mode = LANE_MODE_UNKNOWN; 1016 1012 } 1017 1013 } 1018 1014