aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c8
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/hwif.h4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c60
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c2
-rw-r--r--drivers/net/phy/phylink.c18
-rw-r--r--include/linux/phylink.h2
-rw-r--r--include/linux/stmmac.h2
9 files changed, 70 insertions, 39 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 03b1c5a97826..c6ff1fa0e04d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -68,6 +68,11 @@ static void dwmac4_core_init(struct mac_device_info *hw,
init_waitqueue_head(&priv->tstamp_busy_wait);
}
+static void dwmac4_phylink_get_caps(struct stmmac_priv *priv)
+{
+ priv->phylink_config.mac_capabilities |= MAC_2500FD;
+}
+
static void dwmac4_rx_queue_enable(struct mac_device_info *hw,
u8 mode, u32 queue)
{
@@ -1131,6 +1136,7 @@ static int dwmac4_config_l4_filter(struct mac_device_info *hw, u32 filter_no,
const struct stmmac_ops dwmac4_ops = {
.core_init = dwmac4_core_init,
+ .phylink_get_caps = dwmac4_phylink_get_caps,
.set_mac = stmmac_set_mac,
.rx_ipc = dwmac4_rx_ipc_enable,
.rx_queue_enable = dwmac4_rx_queue_enable,
@@ -1173,6 +1179,7 @@ const struct stmmac_ops dwmac4_ops = {
const struct stmmac_ops dwmac410_ops = {
.core_init = dwmac4_core_init,
+ .phylink_get_caps = dwmac4_phylink_get_caps,
.set_mac = stmmac_dwmac4_set_mac,
.rx_ipc = dwmac4_rx_ipc_enable,
.rx_queue_enable = dwmac4_rx_queue_enable,
@@ -1221,6 +1228,7 @@ const struct stmmac_ops dwmac410_ops = {
const struct stmmac_ops dwmac510_ops = {
.core_init = dwmac4_core_init,
+ .phylink_get_caps = dwmac4_phylink_get_caps,
.set_mac = stmmac_dwmac4_set_mac,
.rx_ipc = dwmac4_rx_ipc_enable,
.rx_queue_enable = dwmac4_rx_queue_enable,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
index 34e1b0c3f346..f352be269deb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
@@ -47,6 +47,14 @@ static void dwxgmac2_core_init(struct mac_device_info *hw,
writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN);
}
+static void xgmac_phylink_get_caps(struct stmmac_priv *priv)
+{
+ priv->phylink_config.mac_capabilities |= MAC_2500FD | MAC_5000FD |
+ MAC_10000FD | MAC_25000FD |
+ MAC_40000FD | MAC_50000FD |
+ MAC_100000FD;
+}
+
static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable)
{
u32 tx = readl(ioaddr + XGMAC_TX_CONFIG);
@@ -1490,6 +1498,7 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, u32 num_txq,
const struct stmmac_ops dwxgmac210_ops = {
.core_init = dwxgmac2_core_init,
+ .phylink_get_caps = xgmac_phylink_get_caps,
.set_mac = dwxgmac2_set_mac,
.rx_ipc = dwxgmac2_rx_ipc,
.rx_queue_enable = dwxgmac2_rx_queue_enable,
@@ -1551,6 +1560,7 @@ static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
const struct stmmac_ops dwxlgmac2_ops = {
.core_init = dwxgmac2_core_init,
+ .phylink_get_caps = xgmac_phylink_get_caps,
.set_mac = dwxgmac2_set_mac,
.rx_ipc = dwxgmac2_rx_ipc,
.rx_queue_enable = dwxlgmac2_rx_queue_enable,
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 238f17c50a1e..b95d3e137813 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -300,6 +300,8 @@ struct stmmac_est;
struct stmmac_ops {
/* MAC core initialization */
void (*core_init)(struct mac_device_info *hw, struct net_device *dev);
+ /* Get phylink capabilities */
+ void (*phylink_get_caps)(struct stmmac_priv *priv);
/* Enable the MAC RX/TX */
void (*set_mac)(void __iomem *ioaddr, bool enable);
/* Enable and verify that the IPC module is supported */
@@ -419,6 +421,8 @@ struct stmmac_ops {
#define stmmac_core_init(__priv, __args...) \
stmmac_do_void_callback(__priv, mac, core_init, __args)
+#define stmmac_mac_phylink_get_caps(__priv) \
+ stmmac_do_void_callback(__priv, mac, phylink_get_caps, __priv)
#define stmmac_mac_set(__priv, __args...) \
stmmac_do_void_callback(__priv, mac, set_mac, __args)
#define stmmac_rx_ipc(__priv, __args...) \
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 7a9bbcf03ea5..33ca5c50bdcd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1153,7 +1153,7 @@ static int stmmac_init_phy(struct net_device *dev)
if (!phylink_expects_phy(priv->phylink))
return 0;
- fwnode = of_fwnode_handle(priv->plat->phylink_node);
+ fwnode = priv->plat->port_node;
if (!fwnode)
fwnode = dev_fwnode(priv->device);
@@ -1199,21 +1199,21 @@ static int stmmac_init_phy(struct net_device *dev)
static int stmmac_phy_setup(struct stmmac_priv *priv)
{
- struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
- struct fwnode_handle *fwnode = of_fwnode_handle(priv->plat->phylink_node);
- int max_speed = priv->plat->max_speed;
+ struct stmmac_mdio_bus_data *mdio_bus_data;
int mode = priv->plat->phy_interface;
+ struct fwnode_handle *fwnode;
struct phylink *phylink;
+ int max_speed;
priv->phylink_config.dev = &priv->dev->dev;
priv->phylink_config.type = PHYLINK_NETDEV;
- if (priv->plat->mdio_bus_data)
+ priv->phylink_config.mac_managed_pm = true;
+
+ mdio_bus_data = priv->plat->mdio_bus_data;
+ if (mdio_bus_data)
priv->phylink_config.ovr_an_inband =
mdio_bus_data->xpcs_an_inband;
- if (!fwnode)
- fwnode = dev_fwnode(priv->device);
-
/* Set the platform/firmware specified interface mode */
__set_bit(mode, priv->phylink_config.supported_interfaces);
@@ -1223,36 +1223,24 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
priv->phylink_config.supported_interfaces);
priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
- MAC_10 | MAC_100;
-
- if (!max_speed || max_speed >= 1000)
- priv->phylink_config.mac_capabilities |= MAC_1000;
-
- if (priv->plat->has_gmac4) {
- if (!max_speed || max_speed >= 2500)
- priv->phylink_config.mac_capabilities |= MAC_2500FD;
- } else if (priv->plat->has_xgmac) {
- if (!max_speed || max_speed >= 2500)
- priv->phylink_config.mac_capabilities |= MAC_2500FD;
- if (!max_speed || max_speed >= 5000)
- priv->phylink_config.mac_capabilities |= MAC_5000FD;
- if (!max_speed || max_speed >= 10000)
- priv->phylink_config.mac_capabilities |= MAC_10000FD;
- if (!max_speed || max_speed >= 25000)
- priv->phylink_config.mac_capabilities |= MAC_25000FD;
- if (!max_speed || max_speed >= 40000)
- priv->phylink_config.mac_capabilities |= MAC_40000FD;
- if (!max_speed || max_speed >= 50000)
- priv->phylink_config.mac_capabilities |= MAC_50000FD;
- if (!max_speed || max_speed >= 100000)
- priv->phylink_config.mac_capabilities |= MAC_100000FD;
- }
+ MAC_10FD | MAC_100FD |
+ MAC_1000FD;
/* Half-Duplex can only work with single queue */
- if (priv->plat->tx_queues_to_use > 1)
- priv->phylink_config.mac_capabilities &=
- ~(MAC_10HD | MAC_100HD | MAC_1000HD);
- priv->phylink_config.mac_managed_pm = true;
+ if (priv->plat->tx_queues_to_use <= 1)
+ priv->phylink_config.mac_capabilities |= MAC_10HD | MAC_100HD |
+ MAC_1000HD;
+
+ /* Get the MAC specific capabilities */
+ stmmac_mac_phylink_get_caps(priv);
+
+ max_speed = priv->plat->max_speed;
+ if (max_speed)
+ phylink_limit_mac_speed(&priv->phylink_config, max_speed);
+
+ fwnode = priv->plat->port_node;
+ if (!fwnode)
+ fwnode = dev_fwnode(priv->device);
phylink = phylink_create(&priv->phylink_config, fwnode,
mode, &stmmac_phylink_mac_ops);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index dd9e2fec5328..fa9e7e7040b9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -533,11 +533,11 @@ int stmmac_mdio_register(struct net_device *ndev)
int err = 0;
struct mii_bus *new_bus;
struct stmmac_priv *priv = netdev_priv(ndev);
- struct fwnode_handle *fwnode = of_fwnode_handle(priv->plat->phylink_node);
struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
struct device_node *mdio_node = priv->plat->mdio_node;
struct device *dev = ndev->dev.parent;
struct fwnode_handle *fixed_node;
+ struct fwnode_handle *fwnode;
int addr, found, max_addr;
if (!mdio_bus_data)
@@ -601,6 +601,7 @@ int stmmac_mdio_register(struct net_device *ndev)
stmmac_xgmac2_mdio_read_c45(new_bus, 0, 0, 0);
/* If fixed-link is set, skip PHY scanning */
+ fwnode = priv->plat->port_node;
if (!fwnode)
fwnode = dev_fwnode(priv->device);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index be8e79c7aa34..ff330423ee66 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -428,7 +428,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
/* PHYLINK automatically parses the phy-handle property */
- plat->phylink_node = np;
+ plat->port_node = of_fwnode_handle(np);
/* Get max speed of operation from device tree */
of_property_read_u32(np, "max-speed", &plat->max_speed);
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 160bce608c34..0d7354955d62 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -427,6 +427,24 @@ static struct {
};
/**
+ * phylink_limit_mac_speed - limit the phylink_config to a maximum speed
+ * @config: pointer to a &struct phylink_config
+ * @max_speed: maximum speed
+ *
+ * Mask off MAC capabilities for speeds higher than the @max_speed parameter.
+ * Any further motifications of config.mac_capabilities will override this.
+ */
+void phylink_limit_mac_speed(struct phylink_config *config, u32 max_speed)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(phylink_caps_params) &&
+ phylink_caps_params[i].speed > max_speed; i++)
+ config->mac_capabilities &= ~phylink_caps_params[i].mask;
+}
+EXPORT_SYMBOL_GPL(phylink_limit_mac_speed);
+
+/**
* phylink_cap_from_speed_duplex - Get mac capability from speed/duplex
* @speed: the speed to search for
* @duplex: the duplex to search for
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 789c516c6b4a..7d07f8736431 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -223,6 +223,8 @@ struct phylink_config {
unsigned long mac_capabilities;
};
+void phylink_limit_mac_speed(struct phylink_config *config, u32 max_speed);
+
/**
* struct phylink_mac_ops - MAC operations structure.
* @validate: Validate and update the link configuration.
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 784277d666eb..b2ccd827bb80 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -227,7 +227,7 @@ struct plat_stmmacenet_data {
phy_interface_t phy_interface;
struct stmmac_mdio_bus_data *mdio_bus_data;
struct device_node *phy_node;
- struct device_node *phylink_node;
+ struct fwnode_handle *port_node;
struct device_node *mdio_node;
struct stmmac_dma_cfg *dma_cfg;
struct stmmac_est *est;