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

Merge branch 'stmmac-next'



Jose Abreu says:

====================
net: stmmac: Improvements for -next

Couple of improvements for -next tree. More info in commit logs.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 83beee5a 94e18382
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ struct stmmac_extra_stats {
	unsigned long rx_missed_cntr;
	unsigned long rx_overflow_cntr;
	unsigned long rx_vlan;
	unsigned long rx_split_hdr_pkt_n;
	/* Tx/Rx IRQ error info */
	unsigned long tx_undeflow_irq;
	unsigned long tx_process_stopped_irq;
@@ -356,6 +357,9 @@ struct dma_features {
	unsigned int addr64;
	unsigned int rssen;
	unsigned int vlhash;
	unsigned int sphen;
	unsigned int vlins;
	unsigned int dvlan;
};

/* GMAC TX FIFO is 8K, Rx FIFO is 16K */
@@ -387,6 +391,12 @@ struct dma_features {
#define STMMAC_RSS_HASH_KEY_SIZE	40
#define STMMAC_RSS_MAX_TABLE_SIZE	256

/* VLAN */
#define STMMAC_VLAN_NONE	0x0
#define STMMAC_VLAN_REMOVE	0x1
#define STMMAC_VLAN_INSERT	0x2
#define STMMAC_VLAN_REPLACE	0x3

extern const struct stmmac_desc_ops enh_desc_ops;
extern const struct stmmac_desc_ops ndesc_ops;

+56 −0
Original line number Diff line number Diff line
@@ -32,6 +32,9 @@
#define XGMAC_CONFIG_ARPEN		BIT(31)
#define XGMAC_CONFIG_GPSL		GENMASK(29, 16)
#define XGMAC_CONFIG_GPSL_SHIFT		16
#define XGMAC_CONFIG_HDSMS		GENMASK(14, 12)
#define XGMAC_CONFIG_HDSMS_SHIFT	12
#define XGMAC_CONFIG_HDSMS_256		(0x2 << XGMAC_CONFIG_HDSMS_SHIFT)
#define XGMAC_CONFIG_S2KP		BIT(11)
#define XGMAC_CONFIG_LM			BIT(10)
#define XGMAC_CONFIG_IPC		BIT(9)
@@ -60,6 +63,11 @@
#define XGMAC_VLAN_ETV			BIT(16)
#define XGMAC_VLAN_VID			GENMASK(15, 0)
#define XGMAC_VLAN_HASH_TABLE		0x00000058
#define XGMAC_VLAN_INCL			0x00000060
#define XGMAC_VLAN_VLTI			BIT(20)
#define XGMAC_VLAN_CSVL			BIT(19)
#define XGMAC_VLAN_VLC			GENMASK(17, 16)
#define XGMAC_VLAN_VLC_SHIFT		16
#define XGMAC_RXQ_CTRL0			0x000000a0
#define XGMAC_RXQEN(x)			GENMASK((x) * 2 + 1, (x) * 2)
#define XGMAC_RXQEN_SHIFT(x)		((x) * 2)
@@ -68,6 +76,7 @@
#define XGMAC_PSRQ(x)			GENMASK((x) * 8 + 7, (x) * 8)
#define XGMAC_PSRQ_SHIFT(x)		((x) * 8)
#define XGMAC_INT_STATUS		0x000000b0
#define XGMAC_LPIIS			BIT(5)
#define XGMAC_PMTIS			BIT(4)
#define XGMAC_INT_EN			0x000000b4
#define XGMAC_TSIE			BIT(12)
@@ -85,10 +94,21 @@
#define XGMAC_RWKPKTEN			BIT(2)
#define XGMAC_MGKPKTEN			BIT(1)
#define XGMAC_PWRDWN			BIT(0)
#define XGMAC_LPI_CTRL			0x000000d0
#define XGMAC_TXCGE			BIT(21)
#define XGMAC_LPITXA			BIT(19)
#define XGMAC_PLS			BIT(17)
#define XGMAC_LPITXEN			BIT(16)
#define XGMAC_RLPIEX			BIT(3)
#define XGMAC_RLPIEN			BIT(2)
#define XGMAC_TLPIEX			BIT(1)
#define XGMAC_TLPIEN			BIT(0)
#define XGMAC_LPI_TIMER_CTRL		0x000000d4
#define XGMAC_HW_FEATURE0		0x0000011c
#define XGMAC_HWFEAT_SAVLANINS		BIT(27)
#define XGMAC_HWFEAT_RXCOESEL		BIT(16)
#define XGMAC_HWFEAT_TXCOESEL		BIT(14)
#define XGMAC_HWFEAT_EEESEL		BIT(13)
#define XGMAC_HWFEAT_TSSEL		BIT(12)
#define XGMAC_HWFEAT_AVSEL		BIT(11)
#define XGMAC_HWFEAT_RAVSEL		BIT(10)
@@ -101,6 +121,7 @@
#define XGMAC_HW_FEATURE1		0x00000120
#define XGMAC_HWFEAT_RSSEN		BIT(20)
#define XGMAC_HWFEAT_TSOEN		BIT(18)
#define XGMAC_HWFEAT_SPHEN		BIT(17)
#define XGMAC_HWFEAT_ADDR64		GENMASK(15, 14)
#define XGMAC_HWFEAT_TXFIFOSIZE		GENMASK(10, 6)
#define XGMAC_HWFEAT_RXFIFOSIZE		GENMASK(4, 0)
@@ -112,6 +133,7 @@
#define XGMAC_HWFEAT_RXQCNT		GENMASK(3, 0)
#define XGMAC_HW_FEATURE3		0x00000128
#define XGMAC_HWFEAT_ASP		GENMASK(15, 14)
#define XGMAC_HWFEAT_DVLAN		BIT(13)
#define XGMAC_HWFEAT_FRPES		GENMASK(12, 11)
#define XGMAC_HWFEAT_FRPPB		GENMASK(10, 9)
#define XGMAC_HWFEAT_FRPSEL		BIT(3)
@@ -145,6 +167,25 @@
#define XGMAC_TXTIMESTAMP_NSEC		0x00000d30
#define XGMAC_TXTSSTSLO			GENMASK(30, 0)
#define XGMAC_TXTIMESTAMP_SEC		0x00000d34
#define XGMAC_PPS_CONTROL		0x00000d70
#define XGMAC_PPS_MAXIDX(x)		((((x) + 1) * 8) - 1)
#define XGMAC_PPS_MINIDX(x)		((x) * 8)
#define XGMAC_PPSx_MASK(x)		\
	GENMASK(XGMAC_PPS_MAXIDX(x), XGMAC_PPS_MINIDX(x))
#define XGMAC_TRGTMODSELx(x, val)	\
	GENMASK(XGMAC_PPS_MAXIDX(x) - 1, XGMAC_PPS_MAXIDX(x) - 2) & \
	((val) << (XGMAC_PPS_MAXIDX(x) - 2))
#define XGMAC_PPSCMDx(x, val)		\
	GENMASK(XGMAC_PPS_MINIDX(x) + 3, XGMAC_PPS_MINIDX(x)) & \
	((val) << XGMAC_PPS_MINIDX(x))
#define XGMAC_PPSCMD_START		0x2
#define XGMAC_PPSCMD_STOP		0x5
#define XGMAC_PPSEN0			BIT(4)
#define XGMAC_PPSx_TARGET_TIME_SEC(x)	(0x00000d80 + (x) * 0x10)
#define XGMAC_PPSx_TARGET_TIME_NSEC(x)	(0x00000d84 + (x) * 0x10)
#define XGMAC_TRGTBUSY0			BIT(31)
#define XGMAC_PPSx_INTERVAL(x)		(0x00000d88 + (x) * 0x10)
#define XGMAC_PPSx_WIDTH(x)		(0x00000d8c + (x) * 0x10)

/* MTL Registers */
#define XGMAC_MTL_OPMODE		0x00001000
@@ -221,6 +262,7 @@
#define XGMAC_RXOVFIS			BIT(16)
#define XGMAC_ABPSIS			BIT(1)
#define XGMAC_TXUNFIS			BIT(0)
#define XGMAC_MAC_REGSIZE		(XGMAC_MTL_QINT_STATUS(15) / 4)

/* DMA Registers */
#define XGMAC_DMA_MODE			0x00003000
@@ -258,6 +300,7 @@
#define XGMAC_TCEIE			BIT(0)
#define XGMAC_DMA_ECC_INT_STATUS	0x0000306c
#define XGMAC_DMA_CH_CONTROL(x)		(0x00003100 + (0x80 * (x)))
#define XGMAC_SPH			BIT(24)
#define XGMAC_PBLx8			BIT(16)
#define XGMAC_DMA_CH_TX_CONTROL(x)	(0x00003104 + (0x80 * (x)))
#define XGMAC_TxPBL			GENMASK(21, 16)
@@ -297,12 +340,17 @@
#define XGMAC_TBU			BIT(2)
#define XGMAC_TPS			BIT(1)
#define XGMAC_TI			BIT(0)
#define XGMAC_REGSIZE			((0x0000317c + (0x80 * 15)) / 4)

/* Descriptors */
#define XGMAC_TDES2_IVT			GENMASK(31, 16)
#define XGMAC_TDES2_IVT_SHIFT		16
#define XGMAC_TDES2_IOC			BIT(31)
#define XGMAC_TDES2_TTSE		BIT(30)
#define XGMAC_TDES2_B2L			GENMASK(29, 16)
#define XGMAC_TDES2_B2L_SHIFT		16
#define XGMAC_TDES2_VTIR		GENMASK(15, 14)
#define XGMAC_TDES2_VTIR_SHIFT		14
#define XGMAC_TDES2_B1L			GENMASK(13, 0)
#define XGMAC_TDES3_OWN			BIT(31)
#define XGMAC_TDES3_CTXT		BIT(30)
@@ -311,13 +359,21 @@
#define XGMAC_TDES3_CPC			GENMASK(27, 26)
#define XGMAC_TDES3_CPC_SHIFT		26
#define XGMAC_TDES3_TCMSSV		BIT(26)
#define XGMAC_TDES3_SAIC		GENMASK(25, 23)
#define XGMAC_TDES3_SAIC_SHIFT		23
#define XGMAC_TDES3_THL			GENMASK(22, 19)
#define XGMAC_TDES3_THL_SHIFT		19
#define XGMAC_TDES3_IVTIR		GENMASK(19, 18)
#define XGMAC_TDES3_IVTIR_SHIFT		18
#define XGMAC_TDES3_TSE			BIT(18)
#define XGMAC_TDES3_IVLTV		BIT(17)
#define XGMAC_TDES3_CIC			GENMASK(17, 16)
#define XGMAC_TDES3_CIC_SHIFT		16
#define XGMAC_TDES3_TPL			GENMASK(17, 0)
#define XGMAC_TDES3_VLTV		BIT(16)
#define XGMAC_TDES3_VT			GENMASK(15, 0)
#define XGMAC_TDES3_FL			GENMASK(14, 0)
#define XGMAC_RDES2_HL			GENMASK(9, 0)
#define XGMAC_RDES3_OWN			BIT(31)
#define XGMAC_RDES3_CTXT		BIT(30)
#define XGMAC_RDES3_IOC			BIT(30)
+176 −6
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <linux/crc32.h>
#include <linux/iopoll.h>
#include "stmmac.h"
#include "stmmac_ptp.h"
#include "dwxgmac2.h"

static void dwxgmac2_core_init(struct mac_device_info *hw,
@@ -238,11 +239,21 @@ static void dwxgmac2_config_cbs(struct mac_device_info *hw,
	writel(value, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(queue));
}

static void dwxgmac2_dump_regs(struct mac_device_info *hw, u32 *reg_space)
{
	void __iomem *ioaddr = hw->pcsr;
	int i;

	for (i = 0; i < XGMAC_MAC_REGSIZE; i++)
		reg_space[i] = readl(ioaddr + i * 4);
}

static int dwxgmac2_host_irq_status(struct mac_device_info *hw,
				    struct stmmac_extra_stats *x)
{
	void __iomem *ioaddr = hw->pcsr;
	u32 stat, en;
	int ret = 0;

	en = readl(ioaddr + XGMAC_INT_EN);
	stat = readl(ioaddr + XGMAC_INT_STATUS);
@@ -254,7 +265,24 @@ static int dwxgmac2_host_irq_status(struct mac_device_info *hw,
		readl(ioaddr + XGMAC_PMT);
	}

	return 0;
	if (stat & XGMAC_LPIIS) {
		u32 lpi = readl(ioaddr + XGMAC_LPI_CTRL);

		if (lpi & XGMAC_TLPIEN) {
			ret |= CORE_IRQ_TX_PATH_IN_LPI_MODE;
			x->irq_tx_path_in_lpi_mode_n++;
		}
		if (lpi & XGMAC_TLPIEX) {
			ret |= CORE_IRQ_TX_PATH_EXIT_LPI_MODE;
			x->irq_tx_path_exit_lpi_mode_n++;
		}
		if (lpi & XGMAC_RLPIEN)
			x->irq_rx_path_in_lpi_mode_n++;
		if (lpi & XGMAC_RLPIEX)
			x->irq_rx_path_exit_lpi_mode_n++;
	}

	return ret;
}

static int dwxgmac2_host_mtl_irq_status(struct mac_device_info *hw, u32 chan)
@@ -347,6 +375,53 @@ static void dwxgmac2_get_umac_addr(struct mac_device_info *hw,
	addr[5] = (hi_addr >> 8) & 0xff;
}

static void dwxgmac2_set_eee_mode(struct mac_device_info *hw,
				  bool en_tx_lpi_clockgating)
{
	void __iomem *ioaddr = hw->pcsr;
	u32 value;

	value = readl(ioaddr + XGMAC_LPI_CTRL);

	value |= XGMAC_LPITXEN | XGMAC_LPITXA;
	if (en_tx_lpi_clockgating)
		value |= XGMAC_TXCGE;

	writel(value, ioaddr + XGMAC_LPI_CTRL);
}

static void dwxgmac2_reset_eee_mode(struct mac_device_info *hw)
{
	void __iomem *ioaddr = hw->pcsr;
	u32 value;

	value = readl(ioaddr + XGMAC_LPI_CTRL);
	value &= ~(XGMAC_LPITXEN | XGMAC_LPITXA | XGMAC_TXCGE);
	writel(value, ioaddr + XGMAC_LPI_CTRL);
}

static void dwxgmac2_set_eee_pls(struct mac_device_info *hw, int link)
{
	void __iomem *ioaddr = hw->pcsr;
	u32 value;

	value = readl(ioaddr + XGMAC_LPI_CTRL);
	if (link)
		value |= XGMAC_PLS;
	else
		value &= ~XGMAC_PLS;
	writel(value, ioaddr + XGMAC_LPI_CTRL);
}

static void dwxgmac2_set_eee_timer(struct mac_device_info *hw, int ls, int tw)
{
	void __iomem *ioaddr = hw->pcsr;
	u32 value;

	value = (tw & 0xffff) | ((ls & 0x3ff) << 16);
	writel(value, ioaddr + XGMAC_LPI_TIMER_CTRL);
}

static void dwxgmac2_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits,
				int mcbitslog2)
{
@@ -997,6 +1072,97 @@ re_enable:
	return ret;
}

static int dwxgmac2_get_mac_tx_timestamp(struct mac_device_info *hw, u64 *ts)
{
	void __iomem *ioaddr = hw->pcsr;
	u32 value;

	if (readl_poll_timeout_atomic(ioaddr + XGMAC_TIMESTAMP_STATUS,
				      value, value & XGMAC_TXTSC, 100, 10000))
		return -EBUSY;

	*ts = readl(ioaddr + XGMAC_TXTIMESTAMP_NSEC) & XGMAC_TXTSSTSLO;
	*ts += readl(ioaddr + XGMAC_TXTIMESTAMP_SEC) * 1000000000ULL;
	return 0;
}

static int dwxgmac2_flex_pps_config(void __iomem *ioaddr, int index,
				    struct stmmac_pps_cfg *cfg, bool enable,
				    u32 sub_second_inc, u32 systime_flags)
{
	u32 tnsec = readl(ioaddr + XGMAC_PPSx_TARGET_TIME_NSEC(index));
	u32 val = readl(ioaddr + XGMAC_PPS_CONTROL);
	u64 period;

	if (!cfg->available)
		return -EINVAL;
	if (tnsec & XGMAC_TRGTBUSY0)
		return -EBUSY;
	if (!sub_second_inc || !systime_flags)
		return -EINVAL;

	val &= ~XGMAC_PPSx_MASK(index);

	if (!enable) {
		val |= XGMAC_PPSCMDx(index, XGMAC_PPSCMD_STOP);
		writel(val, ioaddr + XGMAC_PPS_CONTROL);
		return 0;
	}

	val |= XGMAC_PPSCMDx(index, XGMAC_PPSCMD_START);
	val |= XGMAC_TRGTMODSELx(index, XGMAC_PPSCMD_START);
	val |= XGMAC_PPSEN0;

	writel(cfg->start.tv_sec, ioaddr + XGMAC_PPSx_TARGET_TIME_SEC(index));

	if (!(systime_flags & PTP_TCR_TSCTRLSSR))
		cfg->start.tv_nsec = (cfg->start.tv_nsec * 1000) / 465;
	writel(cfg->start.tv_nsec, ioaddr + XGMAC_PPSx_TARGET_TIME_NSEC(index));

	period = cfg->period.tv_sec * 1000000000;
	period += cfg->period.tv_nsec;

	do_div(period, sub_second_inc);

	if (period <= 1)
		return -EINVAL;

	writel(period - 1, ioaddr + XGMAC_PPSx_INTERVAL(index));

	period >>= 1;
	if (period <= 1)
		return -EINVAL;

	writel(period - 1, ioaddr + XGMAC_PPSx_WIDTH(index));

	/* Finally, activate it */
	writel(val, ioaddr + XGMAC_PPS_CONTROL);
	return 0;
}

static void dwxgmac2_sarc_configure(void __iomem *ioaddr, int val)
{
	u32 value = readl(ioaddr + XGMAC_TX_CONFIG);

	value &= ~XGMAC_CONFIG_SARC;
	value |= val << XGMAC_CONFIG_SARC_SHIFT;

	writel(value, ioaddr + XGMAC_TX_CONFIG);
}

static void dwxgmac2_enable_vlan(struct mac_device_info *hw, u32 type)
{
	void __iomem *ioaddr = hw->pcsr;
	u32 value;

	value = readl(ioaddr + XGMAC_VLAN_INCL);
	value |= XGMAC_VLAN_VLTI;
	value |= XGMAC_VLAN_CSVL; /* Only use SVLAN */
	value &= ~XGMAC_VLAN_VLC;
	value |= (type << XGMAC_VLAN_VLC_SHIFT) & XGMAC_VLAN_VLC;
	writel(value, ioaddr + XGMAC_VLAN_INCL);
}

const struct stmmac_ops dwxgmac210_ops = {
	.core_init = dwxgmac2_core_init,
	.set_mac = dwxgmac2_set_mac,
@@ -1010,17 +1176,17 @@ const struct stmmac_ops dwxgmac210_ops = {
	.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 = NULL,
	.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 = NULL,
	.reset_eee_mode = NULL,
	.set_eee_timer = NULL,
	.set_eee_pls = NULL,
	.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,
@@ -1033,6 +1199,10 @@ const struct stmmac_ops dwxgmac210_ops = {
	.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,
};

int dwxgmac2_setup(struct stmmac_priv *priv)
+73 −12
Original line number Diff line number Diff line
@@ -26,16 +26,17 @@ static int dwxgmac2_get_rx_status(void *data, struct stmmac_extra_stats *x,
				  struct dma_desc *p)
{
	unsigned int rdes3 = le32_to_cpu(p->des3);
	int ret = good_frame;

	if (unlikely(rdes3 & XGMAC_RDES3_OWN))
		return dma_own;
	if (unlikely(rdes3 & XGMAC_RDES3_CTXT))
		return discard_frame;
	if (likely(!(rdes3 & XGMAC_RDES3_LD)))
		return rx_not_ls;
	if (unlikely((rdes3 & XGMAC_RDES3_ES) && (rdes3 & XGMAC_RDES3_LD)))
		return discard_frame;
	if (unlikely(rdes3 & XGMAC_RDES3_ES))
		ret = discard_frame;

	return ret;
	return good_frame;
}

static int dwxgmac2_get_tx_len(struct dma_desc *p)
@@ -55,7 +56,7 @@ static void dwxgmac2_set_tx_owner(struct dma_desc *p)

static void dwxgmac2_set_rx_owner(struct dma_desc *p, int disable_rx_ic)
{
	p->des3 = cpu_to_le32(XGMAC_RDES3_OWN);
	p->des3 |= cpu_to_le32(XGMAC_RDES3_OWN);

	if (!disable_rx_ic)
		p->des3 |= cpu_to_le32(XGMAC_RDES3_IOC);
@@ -98,11 +99,17 @@ static int dwxgmac2_rx_check_timestamp(void *desc)
	unsigned int rdes3 = le32_to_cpu(p->des3);
	bool desc_valid, ts_valid;

	dma_rmb();

	desc_valid = !(rdes3 & XGMAC_RDES3_OWN) && (rdes3 & XGMAC_RDES3_CTXT);
	ts_valid = !(rdes3 & XGMAC_RDES3_TSD) && (rdes3 & XGMAC_RDES3_TSA);

	if (likely(desc_valid && ts_valid))
	if (likely(desc_valid && ts_valid)) {
		if ((p->des0 == 0xffffffff) && (p->des1 == 0xffffffff))
			return -EINVAL;
		return 0;
	}

	return -EINVAL;
}

@@ -113,13 +120,10 @@ static int dwxgmac2_get_rx_timestamp_status(void *desc, void *next_desc,
	unsigned int rdes3 = le32_to_cpu(p->des3);
	int ret = -EBUSY;

	if (likely(rdes3 & XGMAC_RDES3_CDA)) {
	if (likely(rdes3 & XGMAC_RDES3_CDA))
		ret = dwxgmac2_rx_check_timestamp(next_desc);
		if (ret)
			return ret;
	}

	return ret;
	return !ret;
}

static void dwxgmac2_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
@@ -144,7 +148,7 @@ static void dwxgmac2_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,

	p->des2 |= cpu_to_le32(len & XGMAC_TDES2_B1L);

	tdes3 = tot_pkt_len & XGMAC_TDES3_FL;
	tdes3 |= tot_pkt_len & XGMAC_TDES3_FL;
	if (is_fs)
		tdes3 |= XGMAC_TDES3_FD;
	else
@@ -282,6 +286,58 @@ static int dwxgmac2_get_rx_hash(struct dma_desc *p, u32 *hash,
	return -EINVAL;
}

static int dwxgmac2_get_rx_header_len(struct dma_desc *p, unsigned int *len)
{
	*len = le32_to_cpu(p->des2) & XGMAC_RDES2_HL;
	return 0;
}

static void dwxgmac2_set_sec_addr(struct dma_desc *p, dma_addr_t addr)
{
	p->des2 = cpu_to_le32(lower_32_bits(addr));
	p->des3 = cpu_to_le32(upper_32_bits(addr));
}

static void dwxgmac2_set_sarc(struct dma_desc *p, u32 sarc_type)
{
	sarc_type <<= XGMAC_TDES3_SAIC_SHIFT;

	p->des3 |= cpu_to_le32(sarc_type & XGMAC_TDES3_SAIC);
}

static void dwxgmac2_set_vlan_tag(struct dma_desc *p, u16 tag, u16 inner_tag,
				  u32 inner_type)
{
	p->des0 = 0;
	p->des1 = 0;
	p->des2 = 0;
	p->des3 = 0;

	/* Inner VLAN */
	if (inner_type) {
		u32 des = inner_tag << XGMAC_TDES2_IVT_SHIFT;

		des &= XGMAC_TDES2_IVT;
		p->des2 = cpu_to_le32(des);

		des = inner_type << XGMAC_TDES3_IVTIR_SHIFT;
		des &= XGMAC_TDES3_IVTIR;
		p->des3 = cpu_to_le32(des | XGMAC_TDES3_IVLTV);
	}

	/* Outer VLAN */
	p->des3 |= cpu_to_le32(tag & XGMAC_TDES3_VT);
	p->des3 |= cpu_to_le32(XGMAC_TDES3_VLTV);

	p->des3 |= cpu_to_le32(XGMAC_TDES3_CTXT);
}

static void dwxgmac2_set_vlan(struct dma_desc *p, u32 type)
{
	type <<= XGMAC_TDES2_VTIR_SHIFT;
	p->des2 |= cpu_to_le32(type & XGMAC_TDES2_VTIR);
}

const struct stmmac_desc_ops dwxgmac210_desc_ops = {
	.tx_status = dwxgmac2_get_tx_status,
	.rx_status = dwxgmac2_get_rx_status,
@@ -306,4 +362,9 @@ const struct stmmac_desc_ops dwxgmac210_desc_ops = {
	.set_addr = dwxgmac2_set_addr,
	.clear = dwxgmac2_clear,
	.get_rx_hash = dwxgmac2_get_rx_hash,
	.get_rx_header_len = dwxgmac2_get_rx_header_len,
	.set_sec_addr = dwxgmac2_set_sec_addr,
	.set_sarc = dwxgmac2_set_sarc,
	.set_vlan_tag = dwxgmac2_set_vlan_tag,
	.set_vlan = dwxgmac2_set_vlan,
};
+30 −1
Original line number Diff line number Diff line
@@ -128,6 +128,14 @@ static void dwxgmac2_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
	writel(XGMAC_RDPS, ioaddr + XGMAC_RX_EDMA_CTRL);
}

static void dwxgmac2_dma_dump_regs(void __iomem *ioaddr, u32 *reg_space)
{
	int i;

	for (i = (XGMAC_DMA_MODE / 4); i < XGMAC_REGSIZE; i++)
		reg_space[i] = readl(ioaddr + i * 4);
}

static void dwxgmac2_dma_rx_mode(void __iomem *ioaddr, int mode,
				 u32 channel, int fifosz, u8 qmode)
{
@@ -351,8 +359,10 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,

	/*  MAC HW feature 0 */
	hw_cap = readl(ioaddr + XGMAC_HW_FEATURE0);
	dma_cap->vlins = (hw_cap & XGMAC_HWFEAT_SAVLANINS) >> 27;
	dma_cap->rx_coe = (hw_cap & XGMAC_HWFEAT_RXCOESEL) >> 16;
	dma_cap->tx_coe = (hw_cap & XGMAC_HWFEAT_TXCOESEL) >> 14;
	dma_cap->eee = (hw_cap & XGMAC_HWFEAT_EEESEL) >> 13;
	dma_cap->atime_stamp = (hw_cap & XGMAC_HWFEAT_TSSEL) >> 12;
	dma_cap->av = (hw_cap & XGMAC_HWFEAT_AVSEL) >> 11;
	dma_cap->av &= (hw_cap & XGMAC_HWFEAT_RAVSEL) >> 10;
@@ -366,6 +376,7 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
	hw_cap = readl(ioaddr + XGMAC_HW_FEATURE1);
	dma_cap->rssen = (hw_cap & XGMAC_HWFEAT_RSSEN) >> 20;
	dma_cap->tsoen = (hw_cap & XGMAC_HWFEAT_TSOEN) >> 18;
	dma_cap->sphen = (hw_cap & XGMAC_HWFEAT_SPHEN) >> 17;

	dma_cap->addr64 = (hw_cap & XGMAC_HWFEAT_ADDR64) >> 14;
	switch (dma_cap->addr64) {
@@ -403,6 +414,7 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
	/* MAC HW feature 3 */
	hw_cap = readl(ioaddr + XGMAC_HW_FEATURE3);
	dma_cap->asp = (hw_cap & XGMAC_HWFEAT_ASP) >> 14;
	dma_cap->dvlan = (hw_cap & XGMAC_HWFEAT_DVLAN) >> 13;
	dma_cap->frpes = (hw_cap & XGMAC_HWFEAT_FRPES) >> 11;
	dma_cap->frpbs = (hw_cap & XGMAC_HWFEAT_FRPPB) >> 9;
	dma_cap->frpsel = (hw_cap & XGMAC_HWFEAT_FRPSEL) >> 3;
@@ -472,6 +484,22 @@ static void dwxgmac2_set_bfsize(void __iomem *ioaddr, int bfsize, u32 chan)
	writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));
}

static void dwxgmac2_enable_sph(void __iomem *ioaddr, bool en, u32 chan)
{
	u32 value = readl(ioaddr + XGMAC_RX_CONFIG);

	value &= ~XGMAC_CONFIG_HDSMS;
	value |= XGMAC_CONFIG_HDSMS_256; /* Segment max 256 bytes */
	writel(value, ioaddr + XGMAC_RX_CONFIG);

	value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(chan));
	if (en)
		value |= XGMAC_SPH;
	else
		value &= ~XGMAC_SPH;
	writel(value, ioaddr + XGMAC_DMA_CH_CONTROL(chan));
}

const struct stmmac_dma_ops dwxgmac210_dma_ops = {
	.reset = dwxgmac2_dma_reset,
	.init = dwxgmac2_dma_init,
@@ -479,7 +507,7 @@ const struct stmmac_dma_ops dwxgmac210_dma_ops = {
	.init_rx_chan = dwxgmac2_dma_init_rx_chan,
	.init_tx_chan = dwxgmac2_dma_init_tx_chan,
	.axi = dwxgmac2_dma_axi,
	.dump_regs = NULL,
	.dump_regs = dwxgmac2_dma_dump_regs,
	.dma_rx_mode = dwxgmac2_dma_rx_mode,
	.dma_tx_mode = dwxgmac2_dma_tx_mode,
	.enable_dma_irq = dwxgmac2_enable_dma_irq,
@@ -498,4 +526,5 @@ const struct stmmac_dma_ops dwxgmac210_dma_ops = {
	.enable_tso = dwxgmac2_enable_tso,
	.qmode = dwxgmac2_qmode,
	.set_bfsize = dwxgmac2_set_bfsize,
	.enable_sph = dwxgmac2_enable_sph,
};
Loading