Commit 0419c450 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'stmmac-100GB-Enterprise-MAC-support'



Jose Abreu says:

====================
net: stmmac: 100GB Enterprise MAC support

Adds the support for Enterprise MAC IP version which allows operating
speeds up to 100GB.

Patch 1/4, adds the support in XPCS for XLGMII interface that is used in
this kind of Enterprise MAC IPs.

Patch 2/4, adds the XLGMII interface support in stmmac.

Patch 3/4, adds the HW specific support for Enterprise MAC.

We end in patch 4/4, by updating stmmac documentation to mention the
support for this new IP version.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9f57db9b 2462a82c
Loading
Loading
Loading
Loading
+5 −2
Original line number Original line Diff line number Diff line
@@ -32,7 +32,8 @@ is also supported.
DesignWare(R) Cores Ethernet MAC 10/100/1000 Universal version 3.70a
DesignWare(R) Cores Ethernet MAC 10/100/1000 Universal version 3.70a
(and older) and DesignWare(R) Cores Ethernet Quality-of-Service version 4.0
(and older) and DesignWare(R) Cores Ethernet Quality-of-Service version 4.0
(and upper) have been used for developing this driver as well as
(and upper) have been used for developing this driver as well as
DesignWare(R) Cores XGMAC - 10G Ethernet MAC.
DesignWare(R) Cores XGMAC - 10G Ethernet MAC and DesignWare(R) Cores
Enterprise MAC - 100G Ethernet MAC.


This driver supports both the platform bus and PCI.
This driver supports both the platform bus and PCI.


@@ -48,6 +49,8 @@ Cores Ethernet Controllers and corresponding minimum and maximum versions:
+-------------------------------+--------------+--------------+--------------+
+-------------------------------+--------------+--------------+--------------+
| XGMAC - 10G Ethernet MAC      | 2.10a        | N/A          | XGMAC2+      |
| XGMAC - 10G Ethernet MAC      | 2.10a        | N/A          | XGMAC2+      |
+-------------------------------+--------------+--------------+--------------+
+-------------------------------+--------------+--------------+--------------+
| XLGMAC - 100G Ethernet MAC    | 2.00a        | N/A          | XLGMAC2+     |
+-------------------------------+--------------+--------------+--------------+


For questions related to hardware requirements, refer to the documentation
For questions related to hardware requirements, refer to the documentation
supplied with your Ethernet adapter. All hardware requirements listed apply
supplied with your Ethernet adapter. All hardware requirements listed apply
@@ -57,7 +60,7 @@ Feature List
============
============


The following features are available in this driver:
The following features are available in this driver:
 - GMII/MII/RGMII/SGMII/RMII/XGMII Interface
 - GMII/MII/RGMII/SGMII/RMII/XGMII/XLGMII Interface
 - Half-Duplex / Full-Duplex Operation
 - Half-Duplex / Full-Duplex Operation
 - Energy Efficient Ethernet (EEE)
 - Energy Efficient Ethernet (EEE)
 - IEEE 802.3x PAUSE Packets (Flow Control)
 - IEEE 802.3x PAUSE Packets (Flow Control)
+13 −0
Original line number Original line Diff line number Diff line
@@ -34,6 +34,11 @@
#define DWMAC_CORE_5_00		0x50
#define DWMAC_CORE_5_00		0x50
#define DWMAC_CORE_5_10		0x51
#define DWMAC_CORE_5_10		0x51
#define DWXGMAC_CORE_2_10	0x21
#define DWXGMAC_CORE_2_10	0x21
#define DWXLGMAC_CORE_2_00	0x20

/* Device ID */
#define DWXGMAC_ID		0x76
#define DWXLGMAC_ID		0x27


#define STMMAC_CHAN0	0	/* Always supported and default for all chips */
#define STMMAC_CHAN0	0	/* Always supported and default for all chips */


@@ -426,6 +431,12 @@ struct mac_link {
		u32 speed5000;
		u32 speed5000;
		u32 speed10000;
		u32 speed10000;
	} xgmii;
	} xgmii;
	struct {
		u32 speed25000;
		u32 speed40000;
		u32 speed50000;
		u32 speed100000;
	} xlgmii;
};
};


struct mii_regs {
struct mii_regs {
@@ -459,6 +470,7 @@ struct mac_device_info {
	unsigned int pcs;
	unsigned int pcs;
	unsigned int pmt;
	unsigned int pmt;
	unsigned int ps;
	unsigned int ps;
	unsigned int xlgmac;
};
};


struct stmmac_rx_routing {
struct stmmac_rx_routing {
@@ -470,6 +482,7 @@ int dwmac100_setup(struct stmmac_priv *priv);
int dwmac1000_setup(struct stmmac_priv *priv);
int dwmac1000_setup(struct stmmac_priv *priv);
int dwmac4_setup(struct stmmac_priv *priv);
int dwmac4_setup(struct stmmac_priv *priv);
int dwxgmac2_setup(struct stmmac_priv *priv);
int dwxgmac2_setup(struct stmmac_priv *priv);
int dwxlgmac2_setup(struct stmmac_priv *priv);


void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
			 unsigned int high, unsigned int low);
			 unsigned int high, unsigned int low);
+99 −0
Original line number Original line Diff line number Diff line
@@ -9,6 +9,7 @@
#include <linux/iopoll.h>
#include <linux/iopoll.h>
#include "stmmac.h"
#include "stmmac.h"
#include "stmmac_ptp.h"
#include "stmmac_ptp.h"
#include "dwxlgmac2.h"
#include "dwxgmac2.h"
#include "dwxgmac2.h"


static void dwxgmac2_core_init(struct mac_device_info *hw,
static void dwxgmac2_core_init(struct mac_device_info *hw,
@@ -1485,6 +1486,67 @@ const struct stmmac_ops dwxgmac210_ops = {
	.fpe_configure = dwxgmac3_fpe_configure,
	.fpe_configure = dwxgmac3_fpe_configure,
};
};


static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
				      u32 queue)
{
	void __iomem *ioaddr = hw->pcsr;
	u32 value;

	value = readl(ioaddr + XLGMAC_RXQ_ENABLE_CTRL0) & ~XGMAC_RXQEN(queue);
	if (mode == MTL_QUEUE_AVB)
		value |= 0x1 << XGMAC_RXQEN_SHIFT(queue);
	else if (mode == MTL_QUEUE_DCB)
		value |= 0x2 << XGMAC_RXQEN_SHIFT(queue);
	writel(value, ioaddr + XLGMAC_RXQ_ENABLE_CTRL0);
}

const struct stmmac_ops dwxlgmac2_ops = {
	.core_init = dwxgmac2_core_init,
	.set_mac = dwxgmac2_set_mac,
	.rx_ipc = dwxgmac2_rx_ipc,
	.rx_queue_enable = dwxlgmac2_rx_queue_enable,
	.rx_queue_prio = dwxgmac2_rx_queue_prio,
	.tx_queue_prio = dwxgmac2_tx_queue_prio,
	.rx_queue_routing = NULL,
	.prog_mtl_rx_algorithms = dwxgmac2_prog_mtl_rx_algorithms,
	.prog_mtl_tx_algorithms = dwxgmac2_prog_mtl_tx_algorithms,
	.set_mtl_tx_queue_weight = dwxgmac2_set_mtl_tx_queue_weight,
	.map_mtl_to_dma = dwxgmac2_map_mtl_to_dma,
	.config_cbs = dwxgmac2_config_cbs,
	.dump_regs = dwxgmac2_dump_regs,
	.host_irq_status = dwxgmac2_host_irq_status,
	.host_mtl_irq_status = dwxgmac2_host_mtl_irq_status,
	.flow_ctrl = dwxgmac2_flow_ctrl,
	.pmt = dwxgmac2_pmt,
	.set_umac_addr = dwxgmac2_set_umac_addr,
	.get_umac_addr = dwxgmac2_get_umac_addr,
	.set_eee_mode = dwxgmac2_set_eee_mode,
	.reset_eee_mode = dwxgmac2_reset_eee_mode,
	.set_eee_timer = dwxgmac2_set_eee_timer,
	.set_eee_pls = dwxgmac2_set_eee_pls,
	.pcs_ctrl_ane = NULL,
	.pcs_rane = NULL,
	.pcs_get_adv_lp = NULL,
	.debug = NULL,
	.set_filter = dwxgmac2_set_filter,
	.safety_feat_config = dwxgmac3_safety_feat_config,
	.safety_feat_irq_status = dwxgmac3_safety_feat_irq_status,
	.safety_feat_dump = dwxgmac3_safety_feat_dump,
	.set_mac_loopback = dwxgmac2_set_mac_loopback,
	.rss_configure = dwxgmac2_rss_configure,
	.update_vlan_hash = dwxgmac2_update_vlan_hash,
	.rxp_config = dwxgmac3_rxp_config,
	.get_mac_tx_timestamp = dwxgmac2_get_mac_tx_timestamp,
	.flex_pps_config = dwxgmac2_flex_pps_config,
	.sarc_configure = dwxgmac2_sarc_configure,
	.enable_vlan = dwxgmac2_enable_vlan,
	.config_l3_filter = dwxgmac2_config_l3_filter,
	.config_l4_filter = dwxgmac2_config_l4_filter,
	.set_arp_offload = dwxgmac2_set_arp_offload,
	.est_configure = dwxgmac3_est_configure,
	.fpe_configure = dwxgmac3_fpe_configure,
};

int dwxgmac2_setup(struct stmmac_priv *priv)
int dwxgmac2_setup(struct stmmac_priv *priv)
{
{
	struct mac_device_info *mac = priv->hw;
	struct mac_device_info *mac = priv->hw;
@@ -1521,3 +1583,40 @@ int dwxgmac2_setup(struct stmmac_priv *priv)


	return 0;
	return 0;
}
}

int dwxlgmac2_setup(struct stmmac_priv *priv)
{
	struct mac_device_info *mac = priv->hw;

	dev_info(priv->device, "\tXLGMAC\n");

	priv->dev->priv_flags |= IFF_UNICAST_FLT;
	mac->pcsr = priv->ioaddr;
	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
	mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
	mac->mcast_bits_log2 = 0;

	if (mac->multicast_filter_bins)
		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);

	mac->link.duplex = 0;
	mac->link.speed1000 = XLGMAC_CONFIG_SS_1000;
	mac->link.speed2500 = XLGMAC_CONFIG_SS_2500;
	mac->link.xgmii.speed10000 = XLGMAC_CONFIG_SS_10G;
	mac->link.xlgmii.speed25000 = XLGMAC_CONFIG_SS_25G;
	mac->link.xlgmii.speed40000 = XLGMAC_CONFIG_SS_40G;
	mac->link.xlgmii.speed50000 = XLGMAC_CONFIG_SS_50G;
	mac->link.xlgmii.speed100000 = XLGMAC_CONFIG_SS_100G;
	mac->link.speed_mask = XLGMAC_CONFIG_SS;

	mac->mii.addr = XGMAC_MDIO_ADDR;
	mac->mii.data = XGMAC_MDIO_DATA;
	mac->mii.addr_shift = 16;
	mac->mii.addr_mask = GENMASK(20, 16);
	mac->mii.reg_shift = 0;
	mac->mii.reg_mask = GENMASK(15, 0);
	mac->mii.clk_csr_shift = 19;
	mac->mii.clk_csr_mask = GENMASK(21, 19);

	return 0;
}
+22 −0
Original line number Original line Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2020 Synopsys, Inc. and/or its affiliates.
 * Synopsys DesignWare XLGMAC definitions.
 */

#ifndef __STMMAC_DWXLGMAC2_H__
#define __STMMAC_DWXLGMAC2_H__

/* MAC Registers */
#define XLGMAC_CONFIG_SS		GENMASK(30, 28)
#define XLGMAC_CONFIG_SS_SHIFT		28
#define XLGMAC_CONFIG_SS_40G		(0x0 << XLGMAC_CONFIG_SS_SHIFT)
#define XLGMAC_CONFIG_SS_25G		(0x1 << XLGMAC_CONFIG_SS_SHIFT)
#define XLGMAC_CONFIG_SS_50G		(0x2 << XLGMAC_CONFIG_SS_SHIFT)
#define XLGMAC_CONFIG_SS_100G		(0x3 << XLGMAC_CONFIG_SS_SHIFT)
#define XLGMAC_CONFIG_SS_10G		(0x4 << XLGMAC_CONFIG_SS_SHIFT)
#define XLGMAC_CONFIG_SS_2500		(0x6 << XLGMAC_CONFIG_SS_SHIFT)
#define XLGMAC_CONFIG_SS_1000		(0x7 << XLGMAC_CONFIG_SS_SHIFT)
#define XLGMAC_RXQ_ENABLE_CTRL0		0x00000140

#endif /* __STMMAC_DWXLGMAC2_H__ */
+44 −1
Original line number Original line Diff line number Diff line
@@ -23,6 +23,18 @@ static u32 stmmac_get_id(struct stmmac_priv *priv, u32 id_reg)
	return reg & GENMASK(7, 0);
	return reg & GENMASK(7, 0);
}
}


static u32 stmmac_get_dev_id(struct stmmac_priv *priv, u32 id_reg)
{
	u32 reg = readl(priv->ioaddr + id_reg);

	if (!reg) {
		dev_info(priv->device, "Version ID not available\n");
		return 0x0;
	}

	return (reg & GENMASK(15, 8)) >> 8;
}

static void stmmac_dwmac_mode_quirk(struct stmmac_priv *priv)
static void stmmac_dwmac_mode_quirk(struct stmmac_priv *priv)
{
{
	struct mac_device_info *mac = priv->hw;
	struct mac_device_info *mac = priv->hw;
@@ -69,11 +81,18 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
	return 0;
	return 0;
}
}


static int stmmac_dwxlgmac_quirks(struct stmmac_priv *priv)
{
	priv->hw->xlgmac = true;
	return 0;
}

static const struct stmmac_hwif_entry {
static const struct stmmac_hwif_entry {
	bool gmac;
	bool gmac;
	bool gmac4;
	bool gmac4;
	bool xgmac;
	bool xgmac;
	u32 min_id;
	u32 min_id;
	u32 dev_id;
	const struct stmmac_regs_off regs;
	const struct stmmac_regs_off regs;
	const void *desc;
	const void *desc;
	const void *dma;
	const void *dma;
@@ -199,6 +218,7 @@ static const struct stmmac_hwif_entry {
		.gmac4 = false,
		.gmac4 = false,
		.xgmac = true,
		.xgmac = true,
		.min_id = DWXGMAC_CORE_2_10,
		.min_id = DWXGMAC_CORE_2_10,
		.dev_id = DWXGMAC_ID,
		.regs = {
		.regs = {
			.ptp_off = PTP_XGMAC_OFFSET,
			.ptp_off = PTP_XGMAC_OFFSET,
			.mmc_off = MMC_XGMAC_OFFSET,
			.mmc_off = MMC_XGMAC_OFFSET,
@@ -212,6 +232,25 @@ static const struct stmmac_hwif_entry {
		.mmc = &dwxgmac_mmc_ops,
		.mmc = &dwxgmac_mmc_ops,
		.setup = dwxgmac2_setup,
		.setup = dwxgmac2_setup,
		.quirks = NULL,
		.quirks = NULL,
	}, {
		.gmac = false,
		.gmac4 = false,
		.xgmac = true,
		.min_id = DWXLGMAC_CORE_2_00,
		.dev_id = DWXLGMAC_ID,
		.regs = {
			.ptp_off = PTP_XGMAC_OFFSET,
			.mmc_off = MMC_XGMAC_OFFSET,
		},
		.desc = &dwxgmac210_desc_ops,
		.dma = &dwxgmac210_dma_ops,
		.mac = &dwxlgmac2_ops,
		.hwtimestamp = &stmmac_ptp,
		.mode = NULL,
		.tc = &dwmac510_tc_ops,
		.mmc = &dwxgmac_mmc_ops,
		.setup = dwxlgmac2_setup,
		.quirks = stmmac_dwxlgmac_quirks,
	},
	},
};
};


@@ -223,13 +262,15 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
	const struct stmmac_hwif_entry *entry;
	const struct stmmac_hwif_entry *entry;
	struct mac_device_info *mac;
	struct mac_device_info *mac;
	bool needs_setup = true;
	bool needs_setup = true;
	u32 id, dev_id = 0;
	int i, ret;
	int i, ret;
	u32 id;


	if (needs_gmac) {
	if (needs_gmac) {
		id = stmmac_get_id(priv, GMAC_VERSION);
		id = stmmac_get_id(priv, GMAC_VERSION);
	} else if (needs_gmac4 || needs_xgmac) {
	} else if (needs_gmac4 || needs_xgmac) {
		id = stmmac_get_id(priv, GMAC4_VERSION);
		id = stmmac_get_id(priv, GMAC4_VERSION);
		if (needs_xgmac)
			dev_id = stmmac_get_dev_id(priv, GMAC4_VERSION);
	} else {
	} else {
		id = 0;
		id = 0;
	}
	}
@@ -267,6 +308,8 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
		/* Use synopsys_id var because some setups can override this */
		/* Use synopsys_id var because some setups can override this */
		if (priv->synopsys_id < entry->min_id)
		if (priv->synopsys_id < entry->min_id)
			continue;
			continue;
		if (needs_xgmac && (dev_id ^ entry->dev_id))
			continue;


		/* Only use generic HW helpers if needed */
		/* Only use generic HW helpers if needed */
		mac->desc = mac->desc ? : entry->desc;
		mac->desc = mac->desc ? : entry->desc;
Loading