Skip to content

Commit

Permalink
net: stmmac: Integrate it with DesignWare XPCS
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jose Abreu authored and David S. Miller committed Mar 10, 2020
1 parent fcb26bd commit f213bbe
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 2 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/stmicro/stmmac/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand Down
12 changes: 12 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/hwif.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
16 changes: 14 additions & 2 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
27 changes: 27 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions include/linux/stmmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit f213bbe

Please sign in to comment.