lkml.org 
[lkml]   [2019]   [Aug]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v4 11/14] net: phy: adin: implement Energy Detect Powerdown mode
    Date
    The ADIN PHYs support Energy Detect Powerdown mode, which puts the PHY into
    a low power mode when there is no signal on the wire (typically cable
    unplugged).
    This behavior is enabled by default, but can be disabled via device
    property.

    Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
    ---
    drivers/net/phy/adin.c | 40 ++++++++++++++++++++++++++++++++++++++++
    1 file changed, 40 insertions(+)

    diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c
    index ddf0512a9a4d..131a72567f25 100644
    --- a/drivers/net/phy/adin.c
    +++ b/drivers/net/phy/adin.c
    @@ -24,6 +24,11 @@
    #define ADIN1300_AUTO_MDI_EN BIT(10)
    #define ADIN1300_MAN_MDIX_EN BIT(9)

    +#define ADIN1300_PHY_CTRL_STATUS2 0x0015
    +#define ADIN1300_NRG_PD_EN BIT(3)
    +#define ADIN1300_NRG_PD_TX_EN BIT(2)
    +#define ADIN1300_NRG_PD_STATUS BIT(1)
    +
    #define ADIN1300_INT_MASK_REG 0x0018
    #define ADIN1300_INT_MDIO_SYNC_EN BIT(9)
    #define ADIN1300_INT_ANEG_STAT_CHNG_EN BIT(8)
    @@ -136,6 +141,14 @@ static struct adin_clause45_mmd_map adin_clause45_mmd_map[] = {
    { MDIO_MMD_PCS, MDIO_PCS_EEE_WK_ERR, ADIN1300_LPI_WAKE_ERR_CNT_REG },
    };

    +/**
    + * struct adin_priv - ADIN PHY driver private data
    + * edpd_enabled true if Energy Detect Powerdown mode is enabled
    + */
    +struct adin_priv {
    + bool edpd_enabled;
    +};
    +
    static int adin_lookup_reg_value(const struct adin_cfg_reg_map *tbl, int cfg)
    {
    size_t i;
    @@ -244,6 +257,18 @@ static int adin_config_rmii_mode(struct phy_device *phydev)
    ADIN1300_GE_RMII_CFG_REG, reg);
    }

    +static int adin_config_init_edpd(struct phy_device *phydev)
    +{
    + struct adin_priv *priv = phydev->priv;
    +
    + if (priv->edpd_enabled)
    + return phy_set_bits(phydev, ADIN1300_PHY_CTRL_STATUS2,
    + (ADIN1300_NRG_PD_EN | ADIN1300_NRG_PD_TX_EN));
    +
    + return phy_clear_bits(phydev, ADIN1300_PHY_CTRL_STATUS2,
    + (ADIN1300_NRG_PD_EN | ADIN1300_NRG_PD_TX_EN));
    +}
    +
    static int adin_config_init(struct phy_device *phydev)
    {
    int rc;
    @@ -262,6 +287,10 @@ static int adin_config_init(struct phy_device *phydev)
    if (rc < 0)
    return rc;

    + rc = adin_config_init_edpd(phydev);
    + if (rc < 0)
    + return rc;
    +
    phydev_dbg(phydev, "PHY is using mode '%s'\n",
    phy_modes(phydev->interface));

    @@ -481,6 +510,17 @@ static int adin_reset(struct phy_device *phydev)

    static int adin_probe(struct phy_device *phydev)
    {
    + struct device *dev = &phydev->mdio.dev;
    + struct adin_priv *priv;
    +
    + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    + if (!priv)
    + return -ENOMEM;
    +
    + priv->edpd_enabled =
    + device_property_read_bool(dev, "adi,disable-energy-detect");
    + phydev->priv = priv;
    +
    return adin_reset(phydev);
    }

    --
    2.20.1
    \
     
     \ /
      Last update: 2019-08-12 13:25    [W:4.218 / U:0.052 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site