mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 03:53:37 +02:00
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>
This commit is contained in:
parent
bfb859a5cb
commit
84c5a3f000
|
|
@ -82,10 +82,18 @@
|
|||
|
||||
#define RTL8211F_PHYCR2 0x19
|
||||
#define RTL8211F_CLKOUT_EN BIT(0)
|
||||
#define RTL8211F_SYSCLK_SSC_EN BIT(3)
|
||||
#define RTL8211F_PHYCR2_PHY_EEE_ENABLE BIT(5)
|
||||
#define RTL8211F_CLKOUT_SSC_EN BIT(7)
|
||||
#define RTL8211F_CLKOUT_SSC_CAP GENMASK(13, 12)
|
||||
|
||||
#define RTL8211F_INSR 0x1d
|
||||
|
||||
/* RTL8211F SSC settings */
|
||||
#define RTL8211F_SSC_PAGE 0xc44
|
||||
#define RTL8211F_SSC_RXC 0x13
|
||||
#define RTL8211F_SSC_SYSCLK 0x17
|
||||
|
||||
/* RTL8211F LED configuration */
|
||||
#define RTL8211F_LEDCR_PAGE 0xd04
|
||||
#define RTL8211F_LEDCR 0x10
|
||||
|
|
@ -222,6 +230,9 @@ MODULE_LICENSE("GPL");
|
|||
struct rtl821x_priv {
|
||||
bool enable_aldps;
|
||||
bool disable_clk_out;
|
||||
bool enable_clkout_ssc;
|
||||
bool enable_rxc_ssc;
|
||||
bool enable_sysclk_ssc;
|
||||
struct clk *clk;
|
||||
/* rtl8211f */
|
||||
u16 iner;
|
||||
|
|
@ -285,6 +296,12 @@ static int rtl821x_probe(struct phy_device *phydev)
|
|||
"realtek,aldps-enable");
|
||||
priv->disable_clk_out = of_property_read_bool(dev->of_node,
|
||||
"realtek,clkout-disable");
|
||||
priv->enable_clkout_ssc = of_property_read_bool(dev->of_node,
|
||||
"realtek,clkout-ssc-enable");
|
||||
priv->enable_rxc_ssc = of_property_read_bool(dev->of_node,
|
||||
"realtek,rxc-ssc-enable");
|
||||
priv->enable_sysclk_ssc = of_property_read_bool(dev->of_node,
|
||||
"realtek,sysclk-ssc-enable");
|
||||
|
||||
phydev->priv = priv;
|
||||
|
||||
|
|
@ -716,6 +733,104 @@ static int rtl8211f_config_phy_eee(struct phy_device *phydev)
|
|||
RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0);
|
||||
}
|
||||
|
||||
static int rtl8211f_config_clkout_ssc(struct phy_device *phydev)
|
||||
{
|
||||
struct rtl821x_priv *priv = phydev->priv;
|
||||
struct device *dev = &phydev->mdio.dev;
|
||||
int ret;
|
||||
|
||||
/* The value is preserved if the device tree property is absent */
|
||||
if (!priv->enable_clkout_ssc)
|
||||
return 0;
|
||||
|
||||
/* RTL8211FVD has PHYCR2 register, but configuration of CLKOUT SSC
|
||||
* is not currently supported by this driver due to different bit
|
||||
* layout.
|
||||
*/
|
||||
if (phydev->drv->phy_id == RTL_8211FVD_PHYID)
|
||||
return 0;
|
||||
|
||||
/* Unnamed registers from EMI improvement parameters application note 1.2 */
|
||||
ret = phy_write_paged(phydev, 0xd09, 0x10, 0xcf00);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "CLKOUT SSC initialization failed: %pe\n", ERR_PTR(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable CLKOUT SSC and CLKOUT SSC Capability using PHYCR2
|
||||
* bits 7, 12, 13. This matches the register 25 write 0x38C3
|
||||
* from the EMI improvement parameters application note 1.2
|
||||
* section 2.3, without affecting unrelated bits.
|
||||
*/
|
||||
ret = phy_set_bits(phydev, RTL8211F_PHYCR2,
|
||||
RTL8211F_CLKOUT_SSC_CAP | RTL8211F_CLKOUT_SSC_EN);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "CLKOUT SSC enable failed: %pe\n", ERR_PTR(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8211f_config_rxc_ssc(struct phy_device *phydev)
|
||||
{
|
||||
struct rtl821x_priv *priv = phydev->priv;
|
||||
struct device *dev = &phydev->mdio.dev;
|
||||
int ret;
|
||||
|
||||
/* The value is preserved if the device tree property is absent */
|
||||
if (!priv->enable_rxc_ssc)
|
||||
return 0;
|
||||
|
||||
/* RTL8211FVD has PHYCR2 register, but configuration of RXC SSC
|
||||
* is not currently supported by this driver due to different bit
|
||||
* layout.
|
||||
*/
|
||||
if (phydev->drv->phy_id == RTL_8211FVD_PHYID)
|
||||
return 0;
|
||||
|
||||
ret = phy_write_paged(phydev, RTL8211F_SSC_PAGE, RTL8211F_SSC_RXC, 0x5f00);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "RXC SSC configuration failed: %pe\n", ERR_PTR(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8211f_config_sysclk_ssc(struct phy_device *phydev)
|
||||
{
|
||||
struct rtl821x_priv *priv = phydev->priv;
|
||||
struct device *dev = &phydev->mdio.dev;
|
||||
int ret;
|
||||
|
||||
/* The value is preserved if the device tree property is absent */
|
||||
if (!priv->enable_sysclk_ssc)
|
||||
return 0;
|
||||
|
||||
/* RTL8211FVD has PHYCR2 register, but configuration of SYSCLK SSC
|
||||
* is not currently supported by this driver due to different bit
|
||||
* layout.
|
||||
*/
|
||||
if (phydev->drv->phy_id == RTL_8211FVD_PHYID)
|
||||
return 0;
|
||||
|
||||
ret = phy_write_paged(phydev, RTL8211F_SSC_PAGE, RTL8211F_SSC_SYSCLK, 0x4f00);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "SYSCLK SSC configuration failed: %pe\n", ERR_PTR(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable SSC */
|
||||
ret = phy_set_bits(phydev, RTL8211F_PHYCR2, RTL8211F_SYSCLK_SSC_EN);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "SYSCLK SSC enable failed: %pe\n", ERR_PTR(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8211f_config_init(struct phy_device *phydev)
|
||||
{
|
||||
struct device *dev = &phydev->mdio.dev;
|
||||
|
|
@ -732,6 +847,18 @@ static int rtl8211f_config_init(struct phy_device *phydev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rtl8211f_config_rxc_ssc(phydev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rtl8211f_config_sysclk_ssc(phydev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rtl8211f_config_clkout_ssc(phydev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rtl8211f_config_clk_out(phydev);
|
||||
if (ret) {
|
||||
dev_err(dev, "clkout configuration failed: %pe\n",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user