kernel: update stmmac ethernet driver from latest linux-sh4-2.6.32.y - _stm24_0217

This commit is contained in:
Jaroslav Kysela
2016-02-11 21:19:20 +01:00
parent ccc89f44ae
commit dcaf0bf211
34 changed files with 2989 additions and 591 deletions

View File

@@ -277,6 +277,13 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
if (!netdev)
return true;
/* PHY supports WoL+ that has been enabled by ethtool.
* So we can call the suspend function that is expected
* able to program internal registers to wake-up the system.
*/
if (phydev->wol)
return true;
/*
* Don't suspend PHY if the attched netdev parent may wakeup.
* The parent may point to a PCI device, as in tg3 driver.

View File

@@ -299,6 +299,36 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
}
EXPORT_SYMBOL(phy_ethtool_gset);
int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
{
u32 support = phydev->drv->wol_supported;
if (wol->wolopts & ~support)
return -EINVAL;
phydev->wol = wol->wolopts;
if (wol->wolopts) {
device_set_wakeup_enable(&phydev->dev, 1);
enable_irq_wake(phydev->irq);
} else {
device_set_wakeup_enable(&phydev->dev, 0);
disable_irq_wake(phydev->irq);
}
return 0;
}
EXPORT_SYMBOL(phy_ethtool_set_wol);
int phy_ethtool_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
{
if (device_can_wakeup(&phydev->dev)) {
wol->supported = phydev->drv->wol_supported;
wol->wolopts = phydev->wol;
}
return 0;
}
EXPORT_SYMBOL(phy_ethtool_get_wol);
/**
* phy_mii_ioctl - generic PHY MII ioctl interface
* @phydev: the phy_device struct
@@ -510,7 +540,7 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
{
struct phy_device *phydev = phy_dat;
if (PHY_HALTED == phydev->state)
if ((PHY_HALTED == phydev->state) && (!device_may_wakeup(&phydev->dev)))
return IRQ_NONE; /* It can't be ours. */
/* The MDIO bus is not allowed to be written in interrupt
@@ -964,3 +994,35 @@ static void phy_state_machine(struct work_struct *work)
schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ);
}
int phy_read_page(struct phy_device *phydev, u16 regnum, int page)
{
int ret, old;
old = phy_read(phydev, 20);
/* Write the page in 0.20 reg */
phy_write(phydev, 20, page);
/* Read data from user page for the regnum */
ret = phy_read(phydev, regnum);
/* Restore page0 */
phy_write(phydev, 20, old);
return ret;
}
EXPORT_SYMBOL(phy_read_page);
int phy_write_page(struct phy_device *phydev, u16 regnum, int page, int data)
{
int old = phy_read(phydev, 20);
/* Write the page in 0.20 reg */
phy_write(phydev, 20, page);
/* Write date to page for regnum */
phy_write(phydev, regnum, data);
/* Restore page0 */
phy_write(phydev, 20, old);
return 0;
}
EXPORT_SYMBOL(phy_write_page);

View File

@@ -30,6 +30,7 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <linux/mdio.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -874,6 +875,140 @@ int genphy_resume(struct phy_device *phydev)
}
EXPORT_SYMBOL(genphy_resume);
static inline void mmd_phy_cl45(struct mii_bus *bus, int prtad, int devad,
int addr)
{
/* Write the desired MMD Devad */
bus->write(bus, addr, MII_MMD_CRTL, devad);
/* Write the desired MMD register address */
bus->write(bus, addr, MII_MMD_DATA, prtad);
/* Select the Function : DATA with no post increment */
bus->write(bus, addr, MII_MMD_CRTL,
(devad | MII_MMD_CTRL_FUNC_DATA_NOINCR));
}
/**
* read_phy_mmd - reads data from the MMD register (clause 22 to access to
* clause 45)
* @bus: the target MII bus
* @prtad: MMD Address
* @devad: MMD DEVAD
* @addr: PHY address on the MII bus
*
* Description: Reads data from the MMD regisetrs of the
* phy addr. To read these register we have:
* 1) Write reg 13 // DEVAD
* 2) Write reg 14 // MMD Address
* 3) Write reg 13 // MMD Data Command for MMD DEVAD
* 3) Read reg 14 // Read MMD data
*/
static int read_phy_mmd(struct mii_bus *bus, int prtad, int devad, int addr)
{
u32 ret;
mmd_phy_cl45(bus, prtad, devad, addr);
/* Read the content of the MMD's selected register */
ret = bus->read(bus, addr, MII_MMD_DATA);
if (ret < 0)
return -EIO;
return ret;
}
/**
* write_phy_mmd - writes data to the MMD register (clause 22 to access to
* clause 45)
* @bus: the target MII bus
* @prtad: MMD Address
* @devad: MMD DEVAD
* @addr: PHY address on the MII bus
* @data: data to write in the MMD register
*
* Description: write data from the MMD regisetrs of the
* phy addr. To read these register we have:
* 1) Write reg 13 // DEVAD
* 2) Write reg 14 // MMD Address
* 3) Write reg 13 // MMD Data Command for MMD DEVAD
* 3) Write reg 14 // Write MMD data
*/
static void write_phy_mmd(struct mii_bus *bus, int prtad, int devad, int addr,
u32 data)
{
mmd_phy_cl45(bus, prtad, devad, addr);
/* Write the data into MMD's selected register */
bus->write(bus, addr, MII_MMD_DATA, data);
}
/* phy_check_eee
* @dev: device to probe and init
*
* Description: check if the Energy-Efficient Ethernet (EEE)
* is supported by looking at the MMD registers 3.20 and 3.60/61
*/
int phy_check_eee(struct phy_device *phydev)
{
int ret = -EPROTONOSUPPORT;
/* According to 802.3az,the EEE is supported only in full duplex-mode.
* Also EEE feature is active when core is operating with MII, GMII
* or RGMII */
if ((phydev->duplex == DUPLEX_FULL) &&
((phydev->interface == PHY_INTERFACE_MODE_MII) ||
(phydev->interface == PHY_INTERFACE_MODE_GMII) ||
(phydev->interface == PHY_INTERFACE_MODE_RGMII))) {
int eee_cap, eee_link;
/* EEE ability must be supported in both local and remote
* PHY devices. */
eee_cap = read_phy_mmd(phydev->bus, MDIO_EEE_PART_LINK,
MDIO_MMD_AN, phydev->addr);
if (eee_cap < 0)
return eee_cap;
eee_link = read_phy_mmd(phydev->bus, MDIO_EEE_CAP,
MDIO_MMD_PCS, phydev->addr);
if (eee_link < 0)
return eee_link;
if (eee_cap && eee_link) {
/* Configure the PHY to stop receiving xMII clock
* while it is signaling LPI */
int pcs_ctrl = read_phy_mmd(phydev->bus, MDIO_CTRL1,
MDIO_MMD_PCS,
phydev->addr);
if (pcs_ctrl < 0)
return pcs_ctrl;
pcs_ctrl |= MDIO_PCS_CLK_STOP_ENABLE;
write_phy_mmd(phydev->bus, MDIO_CTRL1, MDIO_MMD_PCS,
phydev->addr, pcs_ctrl);
ret = 0; /* EEE supported */
}
}
return ret;
}
EXPORT_SYMBOL(phy_get_eee_err);
/* phy_get_eee_err
* @dev: device to probe and init
*
* Description: it is to report the number of time where the PHY
* failed to complete its normal wake sequence.
*/
int phy_get_eee_err(struct phy_device *phydev)
{
return read_phy_mmd(phydev->bus, MDIO_EEE_WK_ERR, MDIO_MMD_PCS,
phydev->addr);
}
EXPORT_SYMBOL(phy_check_eee);
/**
* phy_probe - probe and init a PHY device
* @dev: device to probe and init
@@ -900,6 +1035,13 @@ static int phy_probe(struct device *dev)
/* Disable the interrupt if the PHY doesn't support it */
if (!(phydrv->flags & PHY_HAS_INTERRUPT))
phydev->irq = PHY_POLL;
else {
/* Check if the PHY is WoL capable but driver cannot work
* in polling mode.
*/
if (phydrv->wol_supported)
device_set_wakeup_capable(dev, 1);
}
mutex_lock(&phydev->lock);