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.

Merge branch 'net-phy-realtek-add-support-for-phy-leds'

Michael Klein says:

====================
net: phy: realtek: Add support for PHY LEDs

Changes in V7:
- Remove some unused macros (patch 1)
- Add more register defines for RTL8211F (patch 3)
- Revise macro definition order once more (patch 4)

Changes in V6:
- fix macro definition order (patch 1)
- introduce two more register defines (patch 2)

Changes in V5:
- Split cleanup patch and improve code formatting

Changes in V4:
- Change (!ret) to (ret == 0)
- Replace set_bit() by __set_bit()

Changes in V3:
- move definition of rtl8211e_read_ext_page() to patch 2
- Wrap overlong lines

Changes in V2:
- Designate to net-next
- Add ExtPage access cleanup patch as suggested by Andrew Lunn
====================

Link: https://patch.msgid.link/20250504172916.243185-1-michael@fossekall.de
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+202 -69
+202 -69
drivers/net/phy/realtek/realtek_main.c
··· 18 18 19 19 #include "realtek.h" 20 20 21 - #define RTL821x_PHYSR 0x11 22 - #define RTL821x_PHYSR_DUPLEX BIT(13) 23 - #define RTL821x_PHYSR_SPEED GENMASK(15, 14) 21 + #define RTL8201F_IER 0x13 22 + 23 + #define RTL8201F_ISR 0x1e 24 + #define RTL8201F_ISR_ANERR BIT(15) 25 + #define RTL8201F_ISR_DUPLEX BIT(13) 26 + #define RTL8201F_ISR_LINK BIT(11) 27 + #define RTL8201F_ISR_MASK (RTL8201F_ISR_ANERR | \ 28 + RTL8201F_ISR_DUPLEX | \ 29 + RTL8201F_ISR_LINK) 24 30 25 31 #define RTL821x_INER 0x12 26 32 #define RTL8211B_INER_INIT 0x6400 ··· 36 30 #define RTL821x_INSR 0x13 37 31 38 32 #define RTL821x_EXT_PAGE_SELECT 0x1e 39 - #define RTL821x_PAGE_SELECT 0x1f 40 33 34 + #define RTL821x_PAGE_SELECT 0x1f 35 + #define RTL821x_SET_EXT_PAGE 0x07 36 + 37 + /* RTL8211E extension page 44/0x2c */ 38 + #define RTL8211E_LEDCR_EXT_PAGE 0x2c 39 + #define RTL8211E_LEDCR1 0x1a 40 + #define RTL8211E_LEDCR1_ACT_TXRX BIT(4) 41 + #define RTL8211E_LEDCR1_MASK BIT(4) 42 + #define RTL8211E_LEDCR1_SHIFT 1 43 + 44 + #define RTL8211E_LEDCR2 0x1c 45 + #define RTL8211E_LEDCR2_LINK_1000 BIT(2) 46 + #define RTL8211E_LEDCR2_LINK_100 BIT(1) 47 + #define RTL8211E_LEDCR2_LINK_10 BIT(0) 48 + #define RTL8211E_LEDCR2_MASK GENMASK(2, 0) 49 + #define RTL8211E_LEDCR2_SHIFT 4 50 + 51 + /* RTL8211E extension page 164/0xa4 */ 52 + #define RTL8211E_RGMII_EXT_PAGE 0xa4 53 + #define RTL8211E_RGMII_DELAY 0x1c 54 + #define RTL8211E_CTRL_DELAY BIT(13) 55 + #define RTL8211E_TX_DELAY BIT(12) 56 + #define RTL8211E_RX_DELAY BIT(11) 57 + #define RTL8211E_DELAY_MASK GENMASK(13, 11) 58 + 59 + /* RTL8211F PHY configuration */ 60 + #define RTL8211F_PHYCR_PAGE 0xa43 41 61 #define RTL8211F_PHYCR1 0x18 62 + #define RTL8211F_ALDPS_PLL_OFF BIT(1) 63 + #define RTL8211F_ALDPS_ENABLE BIT(2) 64 + #define RTL8211F_ALDPS_XTAL_OFF BIT(12) 65 + 42 66 #define RTL8211F_PHYCR2 0x19 43 67 #define RTL8211F_CLKOUT_EN BIT(0) 44 68 #define RTL8211F_PHYCR2_PHY_EEE_ENABLE BIT(5) 45 69 70 + #define RTL8211F_INSR_PAGE 0xa43 46 71 #define RTL8211F_INSR 0x1d 72 + 73 + /* RTL8211F LED configuration */ 74 + #define RTL8211F_LEDCR_PAGE 0xd04 75 + #define RTL8211F_LEDCR 0x10 76 + #define RTL8211F_LEDCR_MODE BIT(15) 77 + #define RTL8211F_LEDCR_ACT_TXRX BIT(4) 78 + #define RTL8211F_LEDCR_LINK_1000 BIT(3) 79 + #define RTL8211F_LEDCR_LINK_100 BIT(1) 80 + #define RTL8211F_LEDCR_LINK_10 BIT(0) 81 + #define RTL8211F_LEDCR_MASK GENMASK(4, 0) 82 + #define RTL8211F_LEDCR_SHIFT 5 83 + 84 + /* RTL8211F RGMII configuration */ 85 + #define RTL8211F_RGMII_PAGE 0xd08 86 + 87 + #define RTL8211F_TXCR 0x11 88 + #define RTL8211F_TX_DELAY BIT(8) 89 + 90 + #define RTL8211F_RXCR 0x15 91 + #define RTL8211F_RX_DELAY BIT(3) 47 92 48 93 /* RTL8211F WOL interrupt configuration */ 49 94 #define RTL8211F_INTBCR_PAGE 0xd40 ··· 113 56 #define RTL8211F_PHYSICAL_ADDR_WORD0 16 114 57 #define RTL8211F_PHYSICAL_ADDR_WORD1 17 115 58 #define RTL8211F_PHYSICAL_ADDR_WORD2 18 116 - 117 - #define RTL8211F_LEDCR 0x10 118 - #define RTL8211F_LEDCR_MODE BIT(15) 119 - #define RTL8211F_LEDCR_ACT_TXRX BIT(4) 120 - #define RTL8211F_LEDCR_LINK_1000 BIT(3) 121 - #define RTL8211F_LEDCR_LINK_100 BIT(1) 122 - #define RTL8211F_LEDCR_LINK_10 BIT(0) 123 - #define RTL8211F_LEDCR_MASK GENMASK(4, 0) 124 - #define RTL8211F_LEDCR_SHIFT 5 125 - 126 - #define RTL8211F_TX_DELAY BIT(8) 127 - #define RTL8211F_RX_DELAY BIT(3) 128 - 129 - #define RTL8211F_ALDPS_PLL_OFF BIT(1) 130 - #define RTL8211F_ALDPS_ENABLE BIT(2) 131 - #define RTL8211F_ALDPS_XTAL_OFF BIT(12) 132 - 133 - #define RTL8211E_CTRL_DELAY BIT(13) 134 - #define RTL8211E_TX_DELAY BIT(12) 135 - #define RTL8211E_RX_DELAY BIT(11) 136 - 137 - #define RTL8201F_ISR 0x1e 138 - #define RTL8201F_ISR_ANERR BIT(15) 139 - #define RTL8201F_ISR_DUPLEX BIT(13) 140 - #define RTL8201F_ISR_LINK BIT(11) 141 - #define RTL8201F_ISR_MASK (RTL8201F_ISR_ANERR | \ 142 - RTL8201F_ISR_DUPLEX | \ 143 - RTL8201F_ISR_LINK) 144 - #define RTL8201F_IER 0x13 145 59 146 60 #define RTL822X_VND1_SERDES_OPTION 0x697a 147 61 #define RTL822X_VND1_SERDES_OPTION_MODE_MASK GENMASK(5, 0) ··· 159 131 #define RTL_8221B_VN_CG 0x001cc84a 160 132 #define RTL_8251B 0x001cc862 161 133 162 - #define RTL8211F_LED_COUNT 3 134 + /* RTL8211E and RTL8211F support up to three LEDs */ 135 + #define RTL8211x_LED_COUNT 3 163 136 164 137 MODULE_DESCRIPTION("Realtek PHY driver"); 165 138 MODULE_AUTHOR("Johnson Leung"); ··· 184 155 return __phy_write(phydev, RTL821x_PAGE_SELECT, page); 185 156 } 186 157 158 + static int rtl821x_read_ext_page(struct phy_device *phydev, u16 ext_page, 159 + u32 regnum) 160 + { 161 + int oldpage, ret = 0; 162 + 163 + oldpage = phy_select_page(phydev, RTL821x_SET_EXT_PAGE); 164 + if (oldpage >= 0) { 165 + ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, ext_page); 166 + if (ret == 0) 167 + ret = __phy_read(phydev, regnum); 168 + } 169 + 170 + return phy_restore_page(phydev, oldpage, ret); 171 + } 172 + 173 + static int rtl821x_modify_ext_page(struct phy_device *phydev, u16 ext_page, 174 + u32 regnum, u16 mask, u16 set) 175 + { 176 + int oldpage, ret = 0; 177 + 178 + oldpage = phy_select_page(phydev, RTL821x_SET_EXT_PAGE); 179 + if (oldpage >= 0) { 180 + ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, ext_page); 181 + if (ret == 0) 182 + ret = __phy_modify(phydev, regnum, mask, set); 183 + } 184 + 185 + return phy_restore_page(phydev, oldpage, ret); 186 + } 187 + 187 188 static int rtl821x_probe(struct phy_device *phydev) 188 189 { 189 190 struct device *dev = &phydev->mdio.dev; ··· 230 171 return dev_err_probe(dev, PTR_ERR(priv->clk), 231 172 "failed to get phy clock\n"); 232 173 233 - ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR1); 174 + ret = phy_read_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1); 234 175 if (ret < 0) 235 176 return ret; 236 177 ··· 240 181 241 182 priv->has_phycr2 = !(phy_id == RTL_8211FVD_PHYID); 242 183 if (priv->has_phycr2) { 243 - ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR2); 184 + ret = phy_read_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2); 244 185 if (ret < 0) 245 186 return ret; 246 187 ··· 276 217 { 277 218 int err; 278 219 279 - err = phy_read_paged(phydev, 0xa43, RTL8211F_INSR); 220 + err = phy_read_paged(phydev, RTL8211F_INSR_PAGE, RTL8211F_INSR); 280 221 281 222 return (err < 0) ? err : 0; 282 223 } ··· 419 360 { 420 361 int irq_status; 421 362 422 - irq_status = phy_read_paged(phydev, 0xa43, RTL8211F_INSR); 363 + irq_status = phy_read_paged(phydev, RTL8211F_INSR_PAGE, RTL8211F_INSR); 423 364 if (irq_status < 0) { 424 365 phy_error(phydev); 425 366 return IRQ_NONE; ··· 516 457 u16 val_txdly, val_rxdly; 517 458 int ret; 518 459 519 - ret = phy_modify_paged_changed(phydev, 0xa43, RTL8211F_PHYCR1, 460 + ret = phy_modify_paged_changed(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1, 520 461 RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF, 521 462 priv->phycr1); 522 463 if (ret < 0) { ··· 550 491 return 0; 551 492 } 552 493 553 - ret = phy_modify_paged_changed(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, 494 + ret = phy_modify_paged_changed(phydev, RTL8211F_RGMII_PAGE, 495 + RTL8211F_TXCR, RTL8211F_TX_DELAY, 554 496 val_txdly); 555 497 if (ret < 0) { 556 498 dev_err(dev, "Failed to update the TX delay register\n"); ··· 566 506 str_enabled_disabled(val_txdly)); 567 507 } 568 508 569 - ret = phy_modify_paged_changed(phydev, 0xd08, 0x15, RTL8211F_RX_DELAY, 509 + ret = phy_modify_paged_changed(phydev, RTL8211F_RGMII_PAGE, 510 + RTL8211F_RXCR, RTL8211F_RX_DELAY, 570 511 val_rxdly); 571 512 if (ret < 0) { 572 513 dev_err(dev, "Failed to update the RX delay register\n"); ··· 583 522 } 584 523 585 524 /* Disable PHY-mode EEE so LPI is passed to the MAC */ 586 - ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2, 525 + ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2, 587 526 RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); 588 527 if (ret) 589 528 return ret; 590 529 591 530 if (priv->has_phycr2) { 592 - ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2, 593 - RTL8211F_CLKOUT_EN, priv->phycr2); 531 + ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, 532 + RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, 533 + priv->phycr2); 594 534 if (ret < 0) { 595 535 dev_err(dev, "clkout configuration failed: %pe\n", 596 536 ERR_PTR(ret)); ··· 638 576 return 0; 639 577 } 640 578 641 - static int rtl8211f_led_hw_is_supported(struct phy_device *phydev, u8 index, 579 + static int rtl8211x_led_hw_is_supported(struct phy_device *phydev, u8 index, 642 580 unsigned long rules) 643 581 { 644 582 const unsigned long mask = BIT(TRIGGER_NETDEV_LINK_10) | ··· 657 595 * rates and Active indication always at all three 10+100+1000 658 596 * link rates. 659 597 * This code currently uses mode B only. 598 + * 599 + * RTL8211E PHY LED has one mode, which works like RTL8211F mode B. 660 600 */ 661 601 662 - if (index >= RTL8211F_LED_COUNT) 602 + if (index >= RTL8211x_LED_COUNT) 663 603 return -EINVAL; 664 604 665 605 /* Filter out any other unsupported triggers. */ ··· 680 616 { 681 617 int val; 682 618 683 - if (index >= RTL8211F_LED_COUNT) 619 + if (index >= RTL8211x_LED_COUNT) 684 620 return -EINVAL; 685 621 686 622 val = phy_read_paged(phydev, 0xd04, RTL8211F_LEDCR); ··· 691 627 val &= RTL8211F_LEDCR_MASK; 692 628 693 629 if (val & RTL8211F_LEDCR_LINK_10) 694 - set_bit(TRIGGER_NETDEV_LINK_10, rules); 630 + __set_bit(TRIGGER_NETDEV_LINK_10, rules); 695 631 696 632 if (val & RTL8211F_LEDCR_LINK_100) 697 - set_bit(TRIGGER_NETDEV_LINK_100, rules); 633 + __set_bit(TRIGGER_NETDEV_LINK_100, rules); 698 634 699 635 if (val & RTL8211F_LEDCR_LINK_1000) 700 - set_bit(TRIGGER_NETDEV_LINK_1000, rules); 636 + __set_bit(TRIGGER_NETDEV_LINK_1000, rules); 701 637 702 638 if (val & RTL8211F_LEDCR_ACT_TXRX) { 703 - set_bit(TRIGGER_NETDEV_RX, rules); 704 - set_bit(TRIGGER_NETDEV_TX, rules); 639 + __set_bit(TRIGGER_NETDEV_RX, rules); 640 + __set_bit(TRIGGER_NETDEV_TX, rules); 705 641 } 706 642 707 643 return 0; ··· 713 649 const u16 mask = RTL8211F_LEDCR_MASK << (RTL8211F_LEDCR_SHIFT * index); 714 650 u16 reg = 0; 715 651 716 - if (index >= RTL8211F_LED_COUNT) 652 + if (index >= RTL8211x_LED_COUNT) 717 653 return -EINVAL; 718 654 719 655 if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) ··· 736 672 return phy_modify_paged(phydev, 0xd04, RTL8211F_LEDCR, mask, reg); 737 673 } 738 674 675 + static int rtl8211e_led_hw_control_get(struct phy_device *phydev, u8 index, 676 + unsigned long *rules) 677 + { 678 + int ret; 679 + u16 cr1, cr2; 680 + 681 + if (index >= RTL8211x_LED_COUNT) 682 + return -EINVAL; 683 + 684 + ret = rtl821x_read_ext_page(phydev, RTL8211E_LEDCR_EXT_PAGE, 685 + RTL8211E_LEDCR1); 686 + if (ret < 0) 687 + return ret; 688 + 689 + cr1 = ret >> RTL8211E_LEDCR1_SHIFT * index; 690 + if (cr1 & RTL8211E_LEDCR1_ACT_TXRX) { 691 + __set_bit(TRIGGER_NETDEV_RX, rules); 692 + __set_bit(TRIGGER_NETDEV_TX, rules); 693 + } 694 + 695 + ret = rtl821x_read_ext_page(phydev, RTL8211E_LEDCR_EXT_PAGE, 696 + RTL8211E_LEDCR2); 697 + if (ret < 0) 698 + return ret; 699 + 700 + cr2 = ret >> RTL8211E_LEDCR2_SHIFT * index; 701 + if (cr2 & RTL8211E_LEDCR2_LINK_10) 702 + __set_bit(TRIGGER_NETDEV_LINK_10, rules); 703 + 704 + if (cr2 & RTL8211E_LEDCR2_LINK_100) 705 + __set_bit(TRIGGER_NETDEV_LINK_100, rules); 706 + 707 + if (cr2 & RTL8211E_LEDCR2_LINK_1000) 708 + __set_bit(TRIGGER_NETDEV_LINK_1000, rules); 709 + 710 + return ret; 711 + } 712 + 713 + static int rtl8211e_led_hw_control_set(struct phy_device *phydev, u8 index, 714 + unsigned long rules) 715 + { 716 + const u16 cr1mask = 717 + RTL8211E_LEDCR1_MASK << (RTL8211E_LEDCR1_SHIFT * index); 718 + const u16 cr2mask = 719 + RTL8211E_LEDCR2_MASK << (RTL8211E_LEDCR2_SHIFT * index); 720 + u16 cr1 = 0, cr2 = 0; 721 + int ret; 722 + 723 + if (index >= RTL8211x_LED_COUNT) 724 + return -EINVAL; 725 + 726 + if (test_bit(TRIGGER_NETDEV_RX, &rules) || 727 + test_bit(TRIGGER_NETDEV_TX, &rules)) { 728 + cr1 |= RTL8211E_LEDCR1_ACT_TXRX; 729 + } 730 + 731 + cr1 <<= RTL8211E_LEDCR1_SHIFT * index; 732 + ret = rtl821x_modify_ext_page(phydev, RTL8211E_LEDCR_EXT_PAGE, 733 + RTL8211E_LEDCR1, cr1mask, cr1); 734 + if (ret < 0) 735 + return ret; 736 + 737 + if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) 738 + cr2 |= RTL8211E_LEDCR2_LINK_10; 739 + 740 + if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) 741 + cr2 |= RTL8211E_LEDCR2_LINK_100; 742 + 743 + if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) 744 + cr2 |= RTL8211E_LEDCR2_LINK_1000; 745 + 746 + cr2 <<= RTL8211E_LEDCR2_SHIFT * index; 747 + ret = rtl821x_modify_ext_page(phydev, RTL8211E_LEDCR_EXT_PAGE, 748 + RTL8211E_LEDCR2, cr2mask, cr2); 749 + 750 + return ret; 751 + } 752 + 739 753 static int rtl8211e_config_init(struct phy_device *phydev) 740 754 { 741 - int ret = 0, oldpage; 742 755 u16 val; 743 756 744 757 /* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */ ··· 845 704 * 12 = RX Delay, 11 = TX Delay 846 705 * 10:0 = Test && debug settings reserved by realtek 847 706 */ 848 - oldpage = phy_select_page(phydev, 0x7); 849 - if (oldpage < 0) 850 - goto err_restore_page; 851 - 852 - ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4); 853 - if (ret) 854 - goto err_restore_page; 855 - 856 - ret = __phy_modify(phydev, 0x1c, RTL8211E_CTRL_DELAY 857 - | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY, 858 - val); 859 - 860 - err_restore_page: 861 - return phy_restore_page(phydev, oldpage, ret); 707 + return rtl821x_modify_ext_page(phydev, RTL8211E_RGMII_EXT_PAGE, 708 + RTL8211E_RGMII_DELAY, 709 + RTL8211E_DELAY_MASK, val); 862 710 } 863 711 864 712 static int rtl8211b_suspend(struct phy_device *phydev) ··· 1589 1459 .resume = genphy_resume, 1590 1460 .read_page = rtl821x_read_page, 1591 1461 .write_page = rtl821x_write_page, 1462 + .led_hw_is_supported = rtl8211x_led_hw_is_supported, 1463 + .led_hw_control_get = rtl8211e_led_hw_control_get, 1464 + .led_hw_control_set = rtl8211e_led_hw_control_set, 1592 1465 }, { 1593 1466 PHY_ID_MATCH_EXACT(0x001cc916), 1594 1467 .name = "RTL8211F Gigabit Ethernet", ··· 1607 1474 .read_page = rtl821x_read_page, 1608 1475 .write_page = rtl821x_write_page, 1609 1476 .flags = PHY_ALWAYS_CALL_SUSPEND, 1610 - .led_hw_is_supported = rtl8211f_led_hw_is_supported, 1477 + .led_hw_is_supported = rtl8211x_led_hw_is_supported, 1611 1478 .led_hw_control_get = rtl8211f_led_hw_control_get, 1612 1479 .led_hw_control_set = rtl8211f_led_hw_control_set, 1613 1480 }, {