Commit 2f27d789 authored by David S. Miller's avatar David S. Miller

Merge branch 'realtek-external-phy-clock'

Detlev Casanova says:

====================
net: phy: realtek: Support external PHY clock

Some PHYs can use an external clock that must be enabled before
communicating with them.

Changes since v3:
 * Do not call genphy_suspend if WoL is enabled.
Changes since v2:
 * Reword documentation commit message
Changes since v1:
 * Remove the clock name as it is not guaranteed to be identical across
   different PHYs
 * Disable/Enable the clock when suspending/resuming
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4cab498f 59e227e2
...@@ -93,6 +93,12 @@ properties: ...@@ -93,6 +93,12 @@ properties:
the turn around line low at end of the control phase of the the turn around line low at end of the control phase of the
MDIO transaction. MDIO transaction.
clocks:
maxItems: 1
description:
External clock connected to the PHY. If not specified it is assumed
that the PHY uses a fixed crystal or an internal oscillator.
enet-phy-lane-swap: enet-phy-lane-swap:
$ref: /schemas/types.yaml#/definitions/flag $ref: /schemas/types.yaml#/definitions/flag
description: description:
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/clk.h>
#define RTL821x_PHYSR 0x11 #define RTL821x_PHYSR 0x11
#define RTL821x_PHYSR_DUPLEX BIT(13) #define RTL821x_PHYSR_DUPLEX BIT(13)
...@@ -80,6 +81,7 @@ struct rtl821x_priv { ...@@ -80,6 +81,7 @@ struct rtl821x_priv {
u16 phycr1; u16 phycr1;
u16 phycr2; u16 phycr2;
bool has_phycr2; bool has_phycr2;
struct clk *clk;
}; };
static int rtl821x_read_page(struct phy_device *phydev) static int rtl821x_read_page(struct phy_device *phydev)
...@@ -103,6 +105,11 @@ static int rtl821x_probe(struct phy_device *phydev) ...@@ -103,6 +105,11 @@ static int rtl821x_probe(struct phy_device *phydev)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
priv->clk = devm_clk_get_optional_enabled(dev, NULL);
if (IS_ERR(priv->clk))
return dev_err_probe(dev, PTR_ERR(priv->clk),
"failed to get phy clock\n");
ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR1); ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR1);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -419,10 +426,31 @@ static int rtl8211f_config_init(struct phy_device *phydev) ...@@ -419,10 +426,31 @@ static int rtl8211f_config_init(struct phy_device *phydev)
return genphy_soft_reset(phydev); return genphy_soft_reset(phydev);
} }
static int rtl821x_suspend(struct phy_device *phydev)
{
struct rtl821x_priv *priv = phydev->priv;
int ret = 0;
if (!phydev->wol_enabled) {
ret = genphy_suspend(phydev);
if (ret)
return ret;
clk_disable_unprepare(priv->clk);
}
return ret;
}
static int rtl821x_resume(struct phy_device *phydev) static int rtl821x_resume(struct phy_device *phydev)
{ {
struct rtl821x_priv *priv = phydev->priv;
int ret; int ret;
if (!phydev->wol_enabled)
clk_prepare_enable(priv->clk);
ret = genphy_resume(phydev); ret = genphy_resume(phydev);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -927,10 +955,11 @@ static struct phy_driver realtek_drvs[] = { ...@@ -927,10 +955,11 @@ static struct phy_driver realtek_drvs[] = {
.read_status = rtlgen_read_status, .read_status = rtlgen_read_status,
.config_intr = &rtl8211f_config_intr, .config_intr = &rtl8211f_config_intr,
.handle_interrupt = rtl8211f_handle_interrupt, .handle_interrupt = rtl8211f_handle_interrupt,
.suspend = genphy_suspend, .suspend = rtl821x_suspend,
.resume = rtl821x_resume, .resume = rtl821x_resume,
.read_page = rtl821x_read_page, .read_page = rtl821x_read_page,
.write_page = rtl821x_write_page, .write_page = rtl821x_write_page,
.flags = PHY_ALWAYS_CALL_SUSPEND,
}, { }, {
PHY_ID_MATCH_EXACT(RTL_8211FVD_PHYID), PHY_ID_MATCH_EXACT(RTL_8211FVD_PHYID),
.name = "RTL8211F-VD Gigabit Ethernet", .name = "RTL8211F-VD Gigabit Ethernet",
...@@ -939,10 +968,11 @@ static struct phy_driver realtek_drvs[] = { ...@@ -939,10 +968,11 @@ static struct phy_driver realtek_drvs[] = {
.read_status = rtlgen_read_status, .read_status = rtlgen_read_status,
.config_intr = &rtl8211f_config_intr, .config_intr = &rtl8211f_config_intr,
.handle_interrupt = rtl8211f_handle_interrupt, .handle_interrupt = rtl8211f_handle_interrupt,
.suspend = genphy_suspend, .suspend = rtl821x_suspend,
.resume = rtl821x_resume, .resume = rtl821x_resume,
.read_page = rtl821x_read_page, .read_page = rtl821x_read_page,
.write_page = rtl821x_write_page, .write_page = rtl821x_write_page,
.flags = PHY_ALWAYS_CALL_SUSPEND,
}, { }, {
.name = "Generic FE-GE Realtek PHY", .name = "Generic FE-GE Realtek PHY",
.match_phy_device = rtlgen_match_phy_device, .match_phy_device = rtlgen_match_phy_device,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment