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"
|
tristate "STMicroelectronics Multi-Gigabit Ethernet driver"
|
||||||
depends on HAS_IOMEM && HAS_DMA
|
depends on HAS_IOMEM && HAS_DMA
|
||||||
select MII
|
select MII
|
||||||
|
select MDIO_XPCS
|
||||||
select PAGE_POOL
|
select PAGE_POOL
|
||||||
select PHYLINK
|
select PHYLINK
|
||||||
select CRC32
|
select CRC32
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include <linux/stmmac.h>
|
#include <linux/stmmac.h>
|
||||||
#include <linux/phy.h>
|
#include <linux/phy.h>
|
||||||
|
#include <linux/mdio-xpcs.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#if IS_ENABLED(CONFIG_VLAN_8021Q)
|
#if IS_ENABLED(CONFIG_VLAN_8021Q)
|
||||||
#define STMMAC_VLAN_TAG_USED
|
#define STMMAC_VLAN_TAG_USED
|
||||||
|
@ -446,6 +447,8 @@ struct mac_device_info {
|
||||||
const struct stmmac_hwtimestamp *ptp;
|
const struct stmmac_hwtimestamp *ptp;
|
||||||
const struct stmmac_tc_ops *tc;
|
const struct stmmac_tc_ops *tc;
|
||||||
const struct stmmac_mmc_ops *mmc;
|
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 mii_regs mii; /* MII register Addresses */
|
||||||
struct mac_link link;
|
struct mac_link link;
|
||||||
void __iomem *pcsr; /* vpointer to device CSRs */
|
void __iomem *pcsr; /* vpointer to device CSRs */
|
||||||
|
|
|
@ -577,6 +577,18 @@ struct stmmac_mmc_ops {
|
||||||
#define stmmac_mmc_read(__priv, __args...) \
|
#define stmmac_mmc_read(__priv, __args...) \
|
||||||
stmmac_do_void_callback(__priv, mmc, read, __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 {
|
struct stmmac_regs_off {
|
||||||
u32 ptp_off;
|
u32 ptp_off;
|
||||||
u32 mmc_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_and(state->advertising, state->advertising, mac_supported);
|
||||||
linkmode_andnot(state->advertising, state->advertising, mask);
|
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,
|
static void stmmac_mac_pcs_get_state(struct phylink_config *config,
|
||||||
struct phylink_link_state *state)
|
struct phylink_link_state *state)
|
||||||
{
|
{
|
||||||
|
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
|
||||||
|
|
||||||
state->link = 0;
|
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,
|
static void stmmac_mac_config(struct phylink_config *config, unsigned int mode,
|
||||||
const struct phylink_link_state *state)
|
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)
|
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));
|
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
|
||||||
u32 ctrl;
|
u32 ctrl;
|
||||||
|
|
||||||
|
stmmac_xpcs_link_up(priv, &priv->hw->xpcs_args, speed, interface);
|
||||||
|
|
||||||
ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
|
ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
|
||||||
ctrl &= ~priv->hw->link.speed_mask;
|
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.dev = &priv->dev->dev;
|
||||||
priv->phylink_config.type = PHYLINK_NETDEV;
|
priv->phylink_config.type = PHYLINK_NETDEV;
|
||||||
|
priv->phylink_config.pcs_poll = true;
|
||||||
|
|
||||||
if (!fwnode)
|
if (!fwnode)
|
||||||
fwnode = dev_fwnode(priv->device);
|
fwnode = dev_fwnode(priv->device);
|
||||||
|
@ -2689,7 +2700,8 @@ static int stmmac_open(struct net_device *dev)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (priv->hw->pcs != STMMAC_PCS_TBI &&
|
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);
|
ret = stmmac_init_phy(dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
netdev_err(priv->dev,
|
netdev_err(priv->dev,
|
||||||
|
|
|
@ -382,6 +382,14 @@ int stmmac_mdio_register(struct net_device *ndev)
|
||||||
max_addr = PHY_MAX_ADDR;
|
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)
|
if (mdio_bus_data->needs_reset)
|
||||||
new_bus->reset = &stmmac_mdio_reset;
|
new_bus->reset = &stmmac_mdio_reset;
|
||||||
|
|
||||||
|
@ -433,6 +441,25 @@ int stmmac_mdio_register(struct net_device *ndev)
|
||||||
found = 1;
|
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) {
|
if (!found && !mdio_node) {
|
||||||
dev_warn(dev, "No PHY found\n");
|
dev_warn(dev, "No PHY found\n");
|
||||||
mdiobus_unregister(new_bus);
|
mdiobus_unregister(new_bus);
|
||||||
|
|
|
@ -80,6 +80,7 @@
|
||||||
|
|
||||||
struct stmmac_mdio_bus_data {
|
struct stmmac_mdio_bus_data {
|
||||||
unsigned int phy_mask;
|
unsigned int phy_mask;
|
||||||
|
unsigned int has_xpcs;
|
||||||
int *irqs;
|
int *irqs;
|
||||||
int probed_phy_irq;
|
int probed_phy_irq;
|
||||||
bool needs_reset;
|
bool needs_reset;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user