forked from luck/tmp_suning_uos_patched
net: stmmac: Integrate it with DesignWare XPCS
Adds all the necessary logic so that stmmac can be used with Synopsys DesignWare XPCS. Signed-off-by: Jose Abreu <Jose.Abreu@synopsys.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
fcb26bd2b6
commit
f213bbe8a9
|
@ -3,6 +3,7 @@ config STMMAC_ETH
|
|||
tristate "STMicroelectronics Multi-Gigabit Ethernet driver"
|
||||
depends on HAS_IOMEM && HAS_DMA
|
||||
select MII
|
||||
select MDIO_XPCS
|
||||
select PAGE_POOL
|
||||
select PHYLINK
|
||||
select CRC32
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/netdevice.h>
|
||||
#include <linux/stmmac.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/mdio-xpcs.h>
|
||||
#include <linux/module.h>
|
||||
#if IS_ENABLED(CONFIG_VLAN_8021Q)
|
||||
#define STMMAC_VLAN_TAG_USED
|
||||
|
@ -446,6 +447,8 @@ struct mac_device_info {
|
|||
const struct stmmac_hwtimestamp *ptp;
|
||||
const struct stmmac_tc_ops *tc;
|
||||
const struct stmmac_mmc_ops *mmc;
|
||||
const struct mdio_xpcs_ops *xpcs;
|
||||
struct mdio_xpcs_args xpcs_args;
|
||||
struct mii_regs mii; /* MII register Addresses */
|
||||
struct mac_link link;
|
||||
void __iomem *pcsr; /* vpointer to device CSRs */
|
||||
|
|
|
@ -577,6 +577,18 @@ struct stmmac_mmc_ops {
|
|||
#define stmmac_mmc_read(__priv, __args...) \
|
||||
stmmac_do_void_callback(__priv, mmc, read, __args)
|
||||
|
||||
/* XPCS callbacks */
|
||||
#define stmmac_xpcs_validate(__priv, __args...) \
|
||||
stmmac_do_callback(__priv, xpcs, validate, __args)
|
||||
#define stmmac_xpcs_config(__priv, __args...) \
|
||||
stmmac_do_callback(__priv, xpcs, config, __args)
|
||||
#define stmmac_xpcs_get_state(__priv, __args...) \
|
||||
stmmac_do_callback(__priv, xpcs, get_state, __args)
|
||||
#define stmmac_xpcs_link_up(__priv, __args...) \
|
||||
stmmac_do_callback(__priv, xpcs, link_up, __args)
|
||||
#define stmmac_xpcs_probe(__priv, __args...) \
|
||||
stmmac_do_callback(__priv, xpcs, probe, __args)
|
||||
|
||||
struct stmmac_regs_off {
|
||||
u32 ptp_off;
|
||||
u32 mmc_off;
|
||||
|
|
|
@ -863,18 +863,26 @@ static void stmmac_validate(struct phylink_config *config,
|
|||
|
||||
linkmode_and(state->advertising, state->advertising, mac_supported);
|
||||
linkmode_andnot(state->advertising, state->advertising, mask);
|
||||
|
||||
/* If PCS is supported, check which modes it supports. */
|
||||
stmmac_xpcs_validate(priv, &priv->hw->xpcs_args, supported, state);
|
||||
}
|
||||
|
||||
static void stmmac_mac_pcs_get_state(struct phylink_config *config,
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
|
||||
|
||||
state->link = 0;
|
||||
stmmac_xpcs_get_state(priv, &priv->hw->xpcs_args, state);
|
||||
}
|
||||
|
||||
static void stmmac_mac_config(struct phylink_config *config, unsigned int mode,
|
||||
const struct phylink_link_state *state)
|
||||
{
|
||||
/* Nothing for now. */
|
||||
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
|
||||
|
||||
stmmac_xpcs_config(priv, &priv->hw->xpcs_args, state);
|
||||
}
|
||||
|
||||
static void stmmac_mac_an_restart(struct phylink_config *config)
|
||||
|
@ -902,6 +910,8 @@ static void stmmac_mac_link_up(struct phylink_config *config,
|
|||
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
|
||||
u32 ctrl;
|
||||
|
||||
stmmac_xpcs_link_up(priv, &priv->hw->xpcs_args, speed, interface);
|
||||
|
||||
ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
|
||||
ctrl &= ~priv->hw->link.speed_mask;
|
||||
|
||||
|
@ -1042,6 +1052,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
|
|||
|
||||
priv->phylink_config.dev = &priv->dev->dev;
|
||||
priv->phylink_config.type = PHYLINK_NETDEV;
|
||||
priv->phylink_config.pcs_poll = true;
|
||||
|
||||
if (!fwnode)
|
||||
fwnode = dev_fwnode(priv->device);
|
||||
|
@ -2689,7 +2700,8 @@ static int stmmac_open(struct net_device *dev)
|
|||
int ret;
|
||||
|
||||
if (priv->hw->pcs != STMMAC_PCS_TBI &&
|
||||
priv->hw->pcs != STMMAC_PCS_RTBI) {
|
||||
priv->hw->pcs != STMMAC_PCS_RTBI &&
|
||||
priv->hw->xpcs == NULL) {
|
||||
ret = stmmac_init_phy(dev);
|
||||
if (ret) {
|
||||
netdev_err(priv->dev,
|
||||
|
|
|
@ -382,6 +382,14 @@ int stmmac_mdio_register(struct net_device *ndev)
|
|||
max_addr = PHY_MAX_ADDR;
|
||||
}
|
||||
|
||||
if (mdio_bus_data->has_xpcs) {
|
||||
priv->hw->xpcs = mdio_xpcs_get_ops();
|
||||
if (!priv->hw->xpcs) {
|
||||
err = -ENODEV;
|
||||
goto bus_register_fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (mdio_bus_data->needs_reset)
|
||||
new_bus->reset = &stmmac_mdio_reset;
|
||||
|
||||
|
@ -433,6 +441,25 @@ int stmmac_mdio_register(struct net_device *ndev)
|
|||
found = 1;
|
||||
}
|
||||
|
||||
/* Try to probe the XPCS by scanning all addresses. */
|
||||
if (priv->hw->xpcs) {
|
||||
struct mdio_xpcs_args *xpcs = &priv->hw->xpcs_args;
|
||||
int ret, mode = priv->plat->phy_interface;
|
||||
max_addr = PHY_MAX_ADDR;
|
||||
|
||||
xpcs->bus = new_bus;
|
||||
|
||||
for (addr = 0; addr < max_addr; addr++) {
|
||||
xpcs->addr = addr;
|
||||
|
||||
ret = stmmac_xpcs_probe(priv, xpcs, mode);
|
||||
if (!ret) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found && !mdio_node) {
|
||||
dev_warn(dev, "No PHY found\n");
|
||||
mdiobus_unregister(new_bus);
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
|
||||
struct stmmac_mdio_bus_data {
|
||||
unsigned int phy_mask;
|
||||
unsigned int has_xpcs;
|
||||
int *irqs;
|
||||
int probed_phy_irq;
|
||||
bool needs_reset;
|
||||
|
|
Loading…
Reference in New Issue
Block a user