Merge branch 'gmii2rgmii-loopback'
Gerhard Engleder says: ==================== Add Xilinx GMII2RGMII loopback support The Xilinx GMII2RGMII driver overrides PHY driver functions in order to configure the device according to the link speed of the PHY attached to it. This is implemented for a normal link but not for loopback. Andrew told me to use phy_loopback and this changes make phy_loopback work in combination with Xilinx GMII2RGMII. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
6985157ce8
@ -233,11 +233,9 @@ static DEFINE_MUTEX(phy_fixup_lock);
|
||||
|
||||
static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
|
||||
{
|
||||
struct device_driver *drv = phydev->mdio.dev.driver;
|
||||
struct phy_driver *phydrv = to_phy_driver(drv);
|
||||
struct net_device *netdev = phydev->attached_dev;
|
||||
|
||||
if (!drv || !phydrv->suspend)
|
||||
if (!phydev->drv->suspend)
|
||||
return false;
|
||||
|
||||
/* PHY not attached? May suspend if the PHY has not already been
|
||||
@ -1821,11 +1819,10 @@ EXPORT_SYMBOL(phy_resume);
|
||||
|
||||
int phy_loopback(struct phy_device *phydev, bool enable)
|
||||
{
|
||||
struct phy_driver *phydrv = to_phy_driver(phydev->mdio.dev.driver);
|
||||
int ret = 0;
|
||||
|
||||
if (!phydrv)
|
||||
return -ENODEV;
|
||||
if (!phydev->drv)
|
||||
return -EIO;
|
||||
|
||||
mutex_lock(&phydev->lock);
|
||||
|
||||
@ -1839,8 +1836,8 @@ int phy_loopback(struct phy_device *phydev, bool enable)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (phydrv->set_loopback)
|
||||
ret = phydrv->set_loopback(phydev, enable);
|
||||
if (phydev->drv->set_loopback)
|
||||
ret = phydev->drv->set_loopback(phydev, enable);
|
||||
else
|
||||
ret = genphy_loopback(phydev, enable);
|
||||
|
||||
|
@ -27,12 +27,28 @@ struct gmii2rgmii {
|
||||
struct mdio_device *mdio;
|
||||
};
|
||||
|
||||
static void xgmiitorgmii_configure(struct gmii2rgmii *priv, int speed)
|
||||
{
|
||||
struct mii_bus *bus = priv->mdio->bus;
|
||||
int addr = priv->mdio->addr;
|
||||
u16 val;
|
||||
|
||||
val = mdiobus_read(bus, addr, XILINX_GMII2RGMII_REG);
|
||||
val &= ~XILINX_GMII2RGMII_SPEED_MASK;
|
||||
|
||||
if (speed == SPEED_1000)
|
||||
val |= BMCR_SPEED1000;
|
||||
else if (speed == SPEED_100)
|
||||
val |= BMCR_SPEED100;
|
||||
else
|
||||
val |= BMCR_SPEED10;
|
||||
|
||||
mdiobus_write(bus, addr, XILINX_GMII2RGMII_REG, val);
|
||||
}
|
||||
|
||||
static int xgmiitorgmii_read_status(struct phy_device *phydev)
|
||||
{
|
||||
struct gmii2rgmii *priv = mdiodev_get_drvdata(&phydev->mdio);
|
||||
struct mii_bus *bus = priv->mdio->bus;
|
||||
int addr = priv->mdio->addr;
|
||||
u16 val = 0;
|
||||
int err;
|
||||
|
||||
if (priv->phy_drv->read_status)
|
||||
@ -42,17 +58,24 @@ static int xgmiitorgmii_read_status(struct phy_device *phydev)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
val = mdiobus_read(bus, addr, XILINX_GMII2RGMII_REG);
|
||||
val &= ~XILINX_GMII2RGMII_SPEED_MASK;
|
||||
xgmiitorgmii_configure(priv, phydev->speed);
|
||||
|
||||
if (phydev->speed == SPEED_1000)
|
||||
val |= BMCR_SPEED1000;
|
||||
else if (phydev->speed == SPEED_100)
|
||||
val |= BMCR_SPEED100;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xgmiitorgmii_set_loopback(struct phy_device *phydev, bool enable)
|
||||
{
|
||||
struct gmii2rgmii *priv = mdiodev_get_drvdata(&phydev->mdio);
|
||||
int err;
|
||||
|
||||
if (priv->phy_drv->set_loopback)
|
||||
err = priv->phy_drv->set_loopback(phydev, enable);
|
||||
else
|
||||
val |= BMCR_SPEED10;
|
||||
err = genphy_loopback(phydev, enable);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
mdiobus_write(bus, addr, XILINX_GMII2RGMII_REG, val);
|
||||
xgmiitorgmii_configure(priv, phydev->speed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -90,6 +113,7 @@ static int xgmiitorgmii_probe(struct mdio_device *mdiodev)
|
||||
memcpy(&priv->conv_phy_drv, priv->phy_dev->drv,
|
||||
sizeof(struct phy_driver));
|
||||
priv->conv_phy_drv.read_status = xgmiitorgmii_read_status;
|
||||
priv->conv_phy_drv.set_loopback = xgmiitorgmii_set_loopback;
|
||||
mdiodev_set_drvdata(&priv->phy_dev->mdio, priv);
|
||||
priv->phy_dev->drv = &priv->conv_phy_drv;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user