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.

net: phy: realtek: Add property to enable SSC

Add support for spread spectrum clocking (SSC) on RTL8211F(D)(I)-CG,
RTL8211FS(I)(-VS)-CG, RTL8211FG(I)(-VS)-CG PHYs. The implementation
follows EMI improvement application note Rev. 1.2 for these PHYs.

The current implementation enables SSC for both RXC and SYSCLK clock
signals. Introduce DT properties 'realtek,clkout-ssc-enable',
'realtek,rxc-ssc-enable' and 'realtek,sysclk-ssc-enable' which control
CLKOUT, RXC and SYSCLK SSC spread spectrum clocking enablement on these
signals.

Signed-off-by: Marek Vasut <marek.vasut@mailbox.org>
Link: https://patch.msgid.link/20260405233008.148974-3-marek.vasut@mailbox.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Marek Vasut and committed by
Jakub Kicinski
84c5a3f0 bfb859a5

+127
+127
drivers/net/phy/realtek/realtek_main.c
··· 82 82 83 83 #define RTL8211F_PHYCR2 0x19 84 84 #define RTL8211F_CLKOUT_EN BIT(0) 85 + #define RTL8211F_SYSCLK_SSC_EN BIT(3) 85 86 #define RTL8211F_PHYCR2_PHY_EEE_ENABLE BIT(5) 87 + #define RTL8211F_CLKOUT_SSC_EN BIT(7) 88 + #define RTL8211F_CLKOUT_SSC_CAP GENMASK(13, 12) 86 89 87 90 #define RTL8211F_INSR 0x1d 91 + 92 + /* RTL8211F SSC settings */ 93 + #define RTL8211F_SSC_PAGE 0xc44 94 + #define RTL8211F_SSC_RXC 0x13 95 + #define RTL8211F_SSC_SYSCLK 0x17 88 96 89 97 /* RTL8211F LED configuration */ 90 98 #define RTL8211F_LEDCR_PAGE 0xd04 ··· 230 222 struct rtl821x_priv { 231 223 bool enable_aldps; 232 224 bool disable_clk_out; 225 + bool enable_clkout_ssc; 226 + bool enable_rxc_ssc; 227 + bool enable_sysclk_ssc; 233 228 struct clk *clk; 234 229 /* rtl8211f */ 235 230 u16 iner; ··· 296 285 "realtek,aldps-enable"); 297 286 priv->disable_clk_out = of_property_read_bool(dev->of_node, 298 287 "realtek,clkout-disable"); 288 + priv->enable_clkout_ssc = of_property_read_bool(dev->of_node, 289 + "realtek,clkout-ssc-enable"); 290 + priv->enable_rxc_ssc = of_property_read_bool(dev->of_node, 291 + "realtek,rxc-ssc-enable"); 292 + priv->enable_sysclk_ssc = of_property_read_bool(dev->of_node, 293 + "realtek,sysclk-ssc-enable"); 299 294 300 295 phydev->priv = priv; 301 296 ··· 733 716 RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0); 734 717 } 735 718 719 + static int rtl8211f_config_clkout_ssc(struct phy_device *phydev) 720 + { 721 + struct rtl821x_priv *priv = phydev->priv; 722 + struct device *dev = &phydev->mdio.dev; 723 + int ret; 724 + 725 + /* The value is preserved if the device tree property is absent */ 726 + if (!priv->enable_clkout_ssc) 727 + return 0; 728 + 729 + /* RTL8211FVD has PHYCR2 register, but configuration of CLKOUT SSC 730 + * is not currently supported by this driver due to different bit 731 + * layout. 732 + */ 733 + if (phydev->drv->phy_id == RTL_8211FVD_PHYID) 734 + return 0; 735 + 736 + /* Unnamed registers from EMI improvement parameters application note 1.2 */ 737 + ret = phy_write_paged(phydev, 0xd09, 0x10, 0xcf00); 738 + if (ret < 0) { 739 + dev_err(dev, "CLKOUT SSC initialization failed: %pe\n", ERR_PTR(ret)); 740 + return ret; 741 + } 742 + 743 + /* Enable CLKOUT SSC and CLKOUT SSC Capability using PHYCR2 744 + * bits 7, 12, 13. This matches the register 25 write 0x38C3 745 + * from the EMI improvement parameters application note 1.2 746 + * section 2.3, without affecting unrelated bits. 747 + */ 748 + ret = phy_set_bits(phydev, RTL8211F_PHYCR2, 749 + RTL8211F_CLKOUT_SSC_CAP | RTL8211F_CLKOUT_SSC_EN); 750 + if (ret < 0) { 751 + dev_err(dev, "CLKOUT SSC enable failed: %pe\n", ERR_PTR(ret)); 752 + return ret; 753 + } 754 + 755 + return 0; 756 + } 757 + 758 + static int rtl8211f_config_rxc_ssc(struct phy_device *phydev) 759 + { 760 + struct rtl821x_priv *priv = phydev->priv; 761 + struct device *dev = &phydev->mdio.dev; 762 + int ret; 763 + 764 + /* The value is preserved if the device tree property is absent */ 765 + if (!priv->enable_rxc_ssc) 766 + return 0; 767 + 768 + /* RTL8211FVD has PHYCR2 register, but configuration of RXC SSC 769 + * is not currently supported by this driver due to different bit 770 + * layout. 771 + */ 772 + if (phydev->drv->phy_id == RTL_8211FVD_PHYID) 773 + return 0; 774 + 775 + ret = phy_write_paged(phydev, RTL8211F_SSC_PAGE, RTL8211F_SSC_RXC, 0x5f00); 776 + if (ret < 0) { 777 + dev_err(dev, "RXC SSC configuration failed: %pe\n", ERR_PTR(ret)); 778 + return ret; 779 + } 780 + 781 + return 0; 782 + } 783 + 784 + static int rtl8211f_config_sysclk_ssc(struct phy_device *phydev) 785 + { 786 + struct rtl821x_priv *priv = phydev->priv; 787 + struct device *dev = &phydev->mdio.dev; 788 + int ret; 789 + 790 + /* The value is preserved if the device tree property is absent */ 791 + if (!priv->enable_sysclk_ssc) 792 + return 0; 793 + 794 + /* RTL8211FVD has PHYCR2 register, but configuration of SYSCLK SSC 795 + * is not currently supported by this driver due to different bit 796 + * layout. 797 + */ 798 + if (phydev->drv->phy_id == RTL_8211FVD_PHYID) 799 + return 0; 800 + 801 + ret = phy_write_paged(phydev, RTL8211F_SSC_PAGE, RTL8211F_SSC_SYSCLK, 0x4f00); 802 + if (ret < 0) { 803 + dev_err(dev, "SYSCLK SSC configuration failed: %pe\n", ERR_PTR(ret)); 804 + return ret; 805 + } 806 + 807 + /* Enable SSC */ 808 + ret = phy_set_bits(phydev, RTL8211F_PHYCR2, RTL8211F_SYSCLK_SSC_EN); 809 + if (ret < 0) { 810 + dev_err(dev, "SYSCLK SSC enable failed: %pe\n", ERR_PTR(ret)); 811 + return ret; 812 + } 813 + 814 + return 0; 815 + } 816 + 736 817 static int rtl8211f_config_init(struct phy_device *phydev) 737 818 { 738 819 struct device *dev = &phydev->mdio.dev; ··· 844 729 } 845 730 846 731 ret = rtl8211f_config_rgmii_delay(phydev); 732 + if (ret) 733 + return ret; 734 + 735 + ret = rtl8211f_config_rxc_ssc(phydev); 736 + if (ret) 737 + return ret; 738 + 739 + ret = rtl8211f_config_sysclk_ssc(phydev); 740 + if (ret) 741 + return ret; 742 + 743 + ret = rtl8211f_config_clkout_ssc(phydev); 847 744 if (ret) 848 745 return ret; 849 746