1d6ddfacdSJose Abreu // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2d6ddfacdSJose Abreu /*
3d6ddfacdSJose Abreu  * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates.
4d6ddfacdSJose Abreu  * stmmac XGMAC support.
5d6ddfacdSJose Abreu  */
6d6ddfacdSJose Abreu 
7d6ddfacdSJose Abreu #include <linux/iopoll.h>
8d6ddfacdSJose Abreu #include "stmmac.h"
9d6ddfacdSJose Abreu #include "dwxgmac2.h"
10d6ddfacdSJose Abreu 
dwxgmac2_dma_reset(void __iomem * ioaddr)11d6ddfacdSJose Abreu static int dwxgmac2_dma_reset(void __iomem *ioaddr)
12d6ddfacdSJose Abreu {
13d6ddfacdSJose Abreu 	u32 value = readl(ioaddr + XGMAC_DMA_MODE);
14d6ddfacdSJose Abreu 
15d6ddfacdSJose Abreu 	/* DMA SW reset */
16d6ddfacdSJose Abreu 	writel(value | XGMAC_SWR, ioaddr + XGMAC_DMA_MODE);
17d6ddfacdSJose Abreu 
18d6ddfacdSJose Abreu 	return readl_poll_timeout(ioaddr + XGMAC_DMA_MODE, value,
19d6ddfacdSJose Abreu 				  !(value & XGMAC_SWR), 0, 100000);
20d6ddfacdSJose Abreu }
21d6ddfacdSJose Abreu 
dwxgmac2_dma_init(void __iomem * ioaddr,struct stmmac_dma_cfg * dma_cfg,int atds)22d6ddfacdSJose Abreu static void dwxgmac2_dma_init(void __iomem *ioaddr,
23d6ddfacdSJose Abreu 			      struct stmmac_dma_cfg *dma_cfg, int atds)
24d6ddfacdSJose Abreu {
25d6ddfacdSJose Abreu 	u32 value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);
26d6ddfacdSJose Abreu 
27d6ddfacdSJose Abreu 	if (dma_cfg->aal)
28d6ddfacdSJose Abreu 		value |= XGMAC_AAL;
29d6ddfacdSJose Abreu 
30968a2978SThierry Reding 	if (dma_cfg->eame)
31968a2978SThierry Reding 		value |= XGMAC_EAME;
32968a2978SThierry Reding 
33968a2978SThierry Reding 	writel(value, ioaddr + XGMAC_DMA_SYSBUS_MODE);
34d6ddfacdSJose Abreu }
35d6ddfacdSJose Abreu 
dwxgmac2_dma_init_chan(struct stmmac_priv * priv,void __iomem * ioaddr,struct stmmac_dma_cfg * dma_cfg,u32 chan)361d84b487SAndrew Halaney static void dwxgmac2_dma_init_chan(struct stmmac_priv *priv,
371d84b487SAndrew Halaney 				   void __iomem *ioaddr,
38d6ddfacdSJose Abreu 				   struct stmmac_dma_cfg *dma_cfg, u32 chan)
39d6ddfacdSJose Abreu {
40d6ddfacdSJose Abreu 	u32 value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(chan));
41d6ddfacdSJose Abreu 
42d6ddfacdSJose Abreu 	if (dma_cfg->pblx8)
43d6ddfacdSJose Abreu 		value |= XGMAC_PBLx8;
44d6ddfacdSJose Abreu 
45d6ddfacdSJose Abreu 	writel(value, ioaddr + XGMAC_DMA_CH_CONTROL(chan));
46d6ddfacdSJose Abreu 	writel(XGMAC_DMA_INT_DEFAULT_EN, ioaddr + XGMAC_DMA_CH_INT_EN(chan));
47d6ddfacdSJose Abreu }
48d6ddfacdSJose Abreu 
dwxgmac2_dma_init_rx_chan(struct stmmac_priv * priv,void __iomem * ioaddr,struct stmmac_dma_cfg * dma_cfg,dma_addr_t phy,u32 chan)491d84b487SAndrew Halaney static void dwxgmac2_dma_init_rx_chan(struct stmmac_priv *priv,
501d84b487SAndrew Halaney 				      void __iomem *ioaddr,
51d6ddfacdSJose Abreu 				      struct stmmac_dma_cfg *dma_cfg,
5206a80a7dSJose Abreu 				      dma_addr_t phy, u32 chan)
53d6ddfacdSJose Abreu {
54d6ddfacdSJose Abreu 	u32 rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
55d6ddfacdSJose Abreu 	u32 value;
56d6ddfacdSJose Abreu 
57d6ddfacdSJose Abreu 	value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));
58d6ddfacdSJose Abreu 	value &= ~XGMAC_RxPBL;
59d6ddfacdSJose Abreu 	value |= (rxpbl << XGMAC_RxPBL_SHIFT) & XGMAC_RxPBL;
60d6ddfacdSJose Abreu 	writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));
61d6ddfacdSJose Abreu 
6206a80a7dSJose Abreu 	writel(upper_32_bits(phy), ioaddr + XGMAC_DMA_CH_RxDESC_HADDR(chan));
6306a80a7dSJose Abreu 	writel(lower_32_bits(phy), ioaddr + XGMAC_DMA_CH_RxDESC_LADDR(chan));
64d6ddfacdSJose Abreu }
65d6ddfacdSJose Abreu 
dwxgmac2_dma_init_tx_chan(struct stmmac_priv * priv,void __iomem * ioaddr,struct stmmac_dma_cfg * dma_cfg,dma_addr_t phy,u32 chan)661d84b487SAndrew Halaney static void dwxgmac2_dma_init_tx_chan(struct stmmac_priv *priv,
671d84b487SAndrew Halaney 				      void __iomem *ioaddr,
68d6ddfacdSJose Abreu 				      struct stmmac_dma_cfg *dma_cfg,
6906a80a7dSJose Abreu 				      dma_addr_t phy, u32 chan)
70d6ddfacdSJose Abreu {
71d6ddfacdSJose Abreu 	u32 txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
72d6ddfacdSJose Abreu 	u32 value;
73d6ddfacdSJose Abreu 
74d6ddfacdSJose Abreu 	value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));
75d6ddfacdSJose Abreu 	value &= ~XGMAC_TxPBL;
76d6ddfacdSJose Abreu 	value |= (txpbl << XGMAC_TxPBL_SHIFT) & XGMAC_TxPBL;
77d6ddfacdSJose Abreu 	value |= XGMAC_OSP;
78d6ddfacdSJose Abreu 	writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));
79d6ddfacdSJose Abreu 
8006a80a7dSJose Abreu 	writel(upper_32_bits(phy), ioaddr + XGMAC_DMA_CH_TxDESC_HADDR(chan));
8106a80a7dSJose Abreu 	writel(lower_32_bits(phy), ioaddr + XGMAC_DMA_CH_TxDESC_LADDR(chan));
82d6ddfacdSJose Abreu }
83d6ddfacdSJose Abreu 
dwxgmac2_dma_axi(void __iomem * ioaddr,struct stmmac_axi * axi)84d6ddfacdSJose Abreu static void dwxgmac2_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
85d6ddfacdSJose Abreu {
86d6ddfacdSJose Abreu 	u32 value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);
87d6ddfacdSJose Abreu 	int i;
88d6ddfacdSJose Abreu 
89d6ddfacdSJose Abreu 	if (axi->axi_lpi_en)
90d6ddfacdSJose Abreu 		value |= XGMAC_EN_LPI;
91d6ddfacdSJose Abreu 	if (axi->axi_xit_frm)
92d6ddfacdSJose Abreu 		value |= XGMAC_LPI_XIT_PKT;
93d6ddfacdSJose Abreu 
94d6ddfacdSJose Abreu 	value &= ~XGMAC_WR_OSR_LMT;
95d6ddfacdSJose Abreu 	value |= (axi->axi_wr_osr_lmt << XGMAC_WR_OSR_LMT_SHIFT) &
96d6ddfacdSJose Abreu 		XGMAC_WR_OSR_LMT;
97d6ddfacdSJose Abreu 
98d6ddfacdSJose Abreu 	value &= ~XGMAC_RD_OSR_LMT;
99d6ddfacdSJose Abreu 	value |= (axi->axi_rd_osr_lmt << XGMAC_RD_OSR_LMT_SHIFT) &
100d6ddfacdSJose Abreu 		XGMAC_RD_OSR_LMT;
101d6ddfacdSJose Abreu 
102900a81ccSJose Abreu 	if (!axi->axi_fb)
103900a81ccSJose Abreu 		value |= XGMAC_UNDEF;
104900a81ccSJose Abreu 
105d6ddfacdSJose Abreu 	value &= ~XGMAC_BLEN;
106d6ddfacdSJose Abreu 	for (i = 0; i < AXI_BLEN; i++) {
107d6ddfacdSJose Abreu 		switch (axi->axi_blen[i]) {
108d6ddfacdSJose Abreu 		case 256:
109d6ddfacdSJose Abreu 			value |= XGMAC_BLEN256;
110d6ddfacdSJose Abreu 			break;
111d6ddfacdSJose Abreu 		case 128:
112d6ddfacdSJose Abreu 			value |= XGMAC_BLEN128;
113d6ddfacdSJose Abreu 			break;
114d6ddfacdSJose Abreu 		case 64:
115d6ddfacdSJose Abreu 			value |= XGMAC_BLEN64;
116d6ddfacdSJose Abreu 			break;
117d6ddfacdSJose Abreu 		case 32:
118d6ddfacdSJose Abreu 			value |= XGMAC_BLEN32;
119d6ddfacdSJose Abreu 			break;
120d6ddfacdSJose Abreu 		case 16:
121d6ddfacdSJose Abreu 			value |= XGMAC_BLEN16;
122d6ddfacdSJose Abreu 			break;
123d6ddfacdSJose Abreu 		case 8:
124d6ddfacdSJose Abreu 			value |= XGMAC_BLEN8;
125d6ddfacdSJose Abreu 			break;
126d6ddfacdSJose Abreu 		case 4:
127d6ddfacdSJose Abreu 			value |= XGMAC_BLEN4;
128d6ddfacdSJose Abreu 			break;
129d6ddfacdSJose Abreu 		}
130d6ddfacdSJose Abreu 	}
131d6ddfacdSJose Abreu 
132d6ddfacdSJose Abreu 	writel(value, ioaddr + XGMAC_DMA_SYSBUS_MODE);
1338fe82bd4SJose Abreu 	writel(XGMAC_TDPS, ioaddr + XGMAC_TX_EDMA_CTRL);
1348fe82bd4SJose Abreu 	writel(XGMAC_RDPS, ioaddr + XGMAC_RX_EDMA_CTRL);
135d6ddfacdSJose Abreu }
136d6ddfacdSJose Abreu 
dwxgmac2_dma_dump_regs(struct stmmac_priv * priv,void __iomem * ioaddr,u32 * reg_space)1371d84b487SAndrew Halaney static void dwxgmac2_dma_dump_regs(struct stmmac_priv *priv,
1381d84b487SAndrew Halaney 				   void __iomem *ioaddr, u32 *reg_space)
139bfc56530SJose Abreu {
140bfc56530SJose Abreu 	int i;
141bfc56530SJose Abreu 
142bfc56530SJose Abreu 	for (i = (XGMAC_DMA_MODE / 4); i < XGMAC_REGSIZE; i++)
143bfc56530SJose Abreu 		reg_space[i] = readl(ioaddr + i * 4);
144bfc56530SJose Abreu }
145bfc56530SJose Abreu 
dwxgmac2_dma_rx_mode(struct stmmac_priv * priv,void __iomem * ioaddr,int mode,u32 channel,int fifosz,u8 qmode)1461d84b487SAndrew Halaney static void dwxgmac2_dma_rx_mode(struct stmmac_priv *priv, void __iomem *ioaddr,
1471d84b487SAndrew Halaney 				 int mode, u32 channel, int fifosz, u8 qmode)
148d6ddfacdSJose Abreu {
149d6ddfacdSJose Abreu 	u32 value = readl(ioaddr + XGMAC_MTL_RXQ_OPMODE(channel));
150d6ddfacdSJose Abreu 	unsigned int rqs = fifosz / 256 - 1;
151d6ddfacdSJose Abreu 
152d6ddfacdSJose Abreu 	if (mode == SF_DMA_MODE) {
153d6ddfacdSJose Abreu 		value |= XGMAC_RSF;
154d6ddfacdSJose Abreu 	} else {
155d6ddfacdSJose Abreu 		value &= ~XGMAC_RSF;
156d6ddfacdSJose Abreu 		value &= ~XGMAC_RTC;
157d6ddfacdSJose Abreu 
158d6ddfacdSJose Abreu 		if (mode <= 64)
159d6ddfacdSJose Abreu 			value |= 0x0 << XGMAC_RTC_SHIFT;
160d6ddfacdSJose Abreu 		else if (mode <= 96)
161d6ddfacdSJose Abreu 			value |= 0x2 << XGMAC_RTC_SHIFT;
162d6ddfacdSJose Abreu 		else
163d6ddfacdSJose Abreu 			value |= 0x3 << XGMAC_RTC_SHIFT;
164d6ddfacdSJose Abreu 	}
165d6ddfacdSJose Abreu 
166d6ddfacdSJose Abreu 	value &= ~XGMAC_RQS;
167d6ddfacdSJose Abreu 	value |= (rqs << XGMAC_RQS_SHIFT) & XGMAC_RQS;
168d6ddfacdSJose Abreu 
169ff82cfc7SJose Abreu 	if ((fifosz >= 4096) && (qmode != MTL_QUEUE_AVB)) {
170ff82cfc7SJose Abreu 		u32 flow = readl(ioaddr + XGMAC_MTL_RXQ_FLOW_CONTROL(channel));
171ff82cfc7SJose Abreu 		unsigned int rfd, rfa;
172ff82cfc7SJose Abreu 
173ff82cfc7SJose Abreu 		value |= XGMAC_EHFC;
174ff82cfc7SJose Abreu 
175ff82cfc7SJose Abreu 		/* Set Threshold for Activating Flow Control to min 2 frames,
176ff82cfc7SJose Abreu 		 * i.e. 1500 * 2 = 3000 bytes.
177ff82cfc7SJose Abreu 		 *
178ff82cfc7SJose Abreu 		 * Set Threshold for Deactivating Flow Control to min 1 frame,
179ff82cfc7SJose Abreu 		 * i.e. 1500 bytes.
180ff82cfc7SJose Abreu 		 */
181ff82cfc7SJose Abreu 		switch (fifosz) {
182ff82cfc7SJose Abreu 		case 4096:
183ff82cfc7SJose Abreu 			/* This violates the above formula because of FIFO size
184ff82cfc7SJose Abreu 			 * limit therefore overflow may occur in spite of this.
185ff82cfc7SJose Abreu 			 */
186ff82cfc7SJose Abreu 			rfd = 0x03; /* Full-2.5K */
187ff82cfc7SJose Abreu 			rfa = 0x01; /* Full-1.5K */
188ff82cfc7SJose Abreu 			break;
189ff82cfc7SJose Abreu 
190ff82cfc7SJose Abreu 		default:
19152f96cd1SJose Abreu 			rfd = 0x07; /* Full-4.5K */
19252f96cd1SJose Abreu 			rfa = 0x04; /* Full-3K */
193ff82cfc7SJose Abreu 			break;
194ff82cfc7SJose Abreu 		}
195ff82cfc7SJose Abreu 
196ff82cfc7SJose Abreu 		flow &= ~XGMAC_RFD;
197ff82cfc7SJose Abreu 		flow |= rfd << XGMAC_RFD_SHIFT;
198ff82cfc7SJose Abreu 
199ff82cfc7SJose Abreu 		flow &= ~XGMAC_RFA;
200ff82cfc7SJose Abreu 		flow |= rfa << XGMAC_RFA_SHIFT;
201ff82cfc7SJose Abreu 
202ff82cfc7SJose Abreu 		writel(flow, ioaddr + XGMAC_MTL_RXQ_FLOW_CONTROL(channel));
203ff82cfc7SJose Abreu 	}
204ff82cfc7SJose Abreu 
205d6ddfacdSJose Abreu 	writel(value, ioaddr + XGMAC_MTL_RXQ_OPMODE(channel));
206d6ddfacdSJose Abreu 
207d6ddfacdSJose Abreu 	/* Enable MTL RX overflow */
208d6ddfacdSJose Abreu 	value = readl(ioaddr + XGMAC_MTL_QINTEN(channel));
209d6ddfacdSJose Abreu 	writel(value | XGMAC_RXOIE, ioaddr + XGMAC_MTL_QINTEN(channel));
210d6ddfacdSJose Abreu }
211d6ddfacdSJose Abreu 
dwxgmac2_dma_tx_mode(struct stmmac_priv * priv,void __iomem * ioaddr,int mode,u32 channel,int fifosz,u8 qmode)2121d84b487SAndrew Halaney static void dwxgmac2_dma_tx_mode(struct stmmac_priv *priv, void __iomem *ioaddr,
2131d84b487SAndrew Halaney 				 int mode, u32 channel, int fifosz, u8 qmode)
214d6ddfacdSJose Abreu {
215d6ddfacdSJose Abreu 	u32 value = readl(ioaddr + XGMAC_MTL_TXQ_OPMODE(channel));
216d6ddfacdSJose Abreu 	unsigned int tqs = fifosz / 256 - 1;
217d6ddfacdSJose Abreu 
218d6ddfacdSJose Abreu 	if (mode == SF_DMA_MODE) {
219d6ddfacdSJose Abreu 		value |= XGMAC_TSF;
220d6ddfacdSJose Abreu 	} else {
221d6ddfacdSJose Abreu 		value &= ~XGMAC_TSF;
222d6ddfacdSJose Abreu 		value &= ~XGMAC_TTC;
223d6ddfacdSJose Abreu 
224d6ddfacdSJose Abreu 		if (mode <= 64)
225d6ddfacdSJose Abreu 			value |= 0x0 << XGMAC_TTC_SHIFT;
226d6ddfacdSJose Abreu 		else if (mode <= 96)
227d6ddfacdSJose Abreu 			value |= 0x2 << XGMAC_TTC_SHIFT;
228d6ddfacdSJose Abreu 		else if (mode <= 128)
229d6ddfacdSJose Abreu 			value |= 0x3 << XGMAC_TTC_SHIFT;
230d6ddfacdSJose Abreu 		else if (mode <= 192)
231d6ddfacdSJose Abreu 			value |= 0x4 << XGMAC_TTC_SHIFT;
232d6ddfacdSJose Abreu 		else if (mode <= 256)
233d6ddfacdSJose Abreu 			value |= 0x5 << XGMAC_TTC_SHIFT;
234d6ddfacdSJose Abreu 		else if (mode <= 384)
235d6ddfacdSJose Abreu 			value |= 0x6 << XGMAC_TTC_SHIFT;
236d6ddfacdSJose Abreu 		else
237d6ddfacdSJose Abreu 			value |= 0x7 << XGMAC_TTC_SHIFT;
238d6ddfacdSJose Abreu 	}
239d6ddfacdSJose Abreu 
240ec6ea8e3SJose Abreu 	/* Use static TC to Queue mapping */
241ec6ea8e3SJose Abreu 	value |= (channel << XGMAC_Q2TCMAP_SHIFT) & XGMAC_Q2TCMAP;
242ec6ea8e3SJose Abreu 
243d6ddfacdSJose Abreu 	value &= ~XGMAC_TXQEN;
244d6ddfacdSJose Abreu 	if (qmode != MTL_QUEUE_AVB)
245d6ddfacdSJose Abreu 		value |= 0x2 << XGMAC_TXQEN_SHIFT;
246d6ddfacdSJose Abreu 	else
247d6ddfacdSJose Abreu 		value |= 0x1 << XGMAC_TXQEN_SHIFT;
248d6ddfacdSJose Abreu 
249d6ddfacdSJose Abreu 	value &= ~XGMAC_TQS;
250d6ddfacdSJose Abreu 	value |= (tqs << XGMAC_TQS_SHIFT) & XGMAC_TQS;
251d6ddfacdSJose Abreu 
252d6ddfacdSJose Abreu 	writel(value, ioaddr +  XGMAC_MTL_TXQ_OPMODE(channel));
253d6ddfacdSJose Abreu }
254d6ddfacdSJose Abreu 
dwxgmac2_enable_dma_irq(struct stmmac_priv * priv,void __iomem * ioaddr,u32 chan,bool rx,bool tx)2551d84b487SAndrew Halaney static void dwxgmac2_enable_dma_irq(struct stmmac_priv *priv,
2561d84b487SAndrew Halaney 				    void __iomem *ioaddr, u32 chan,
257021bd5e3SJose Abreu 				    bool rx, bool tx)
258d6ddfacdSJose Abreu {
259021bd5e3SJose Abreu 	u32 value = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));
260021bd5e3SJose Abreu 
261021bd5e3SJose Abreu 	if (rx)
262021bd5e3SJose Abreu 		value |= XGMAC_DMA_INT_DEFAULT_RX;
263021bd5e3SJose Abreu 	if (tx)
264021bd5e3SJose Abreu 		value |= XGMAC_DMA_INT_DEFAULT_TX;
265021bd5e3SJose Abreu 
266021bd5e3SJose Abreu 	writel(value, ioaddr + XGMAC_DMA_CH_INT_EN(chan));
267d6ddfacdSJose Abreu }
268d6ddfacdSJose Abreu 
dwxgmac2_disable_dma_irq(struct stmmac_priv * priv,void __iomem * ioaddr,u32 chan,bool rx,bool tx)2691d84b487SAndrew Halaney static void dwxgmac2_disable_dma_irq(struct stmmac_priv *priv,
2701d84b487SAndrew Halaney 				     void __iomem *ioaddr, u32 chan,
271021bd5e3SJose Abreu 				     bool rx, bool tx)
272d6ddfacdSJose Abreu {
273021bd5e3SJose Abreu 	u32 value = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));
274021bd5e3SJose Abreu 
275021bd5e3SJose Abreu 	if (rx)
276021bd5e3SJose Abreu 		value &= ~XGMAC_DMA_INT_DEFAULT_RX;
277021bd5e3SJose Abreu 	if (tx)
278021bd5e3SJose Abreu 		value &= ~XGMAC_DMA_INT_DEFAULT_TX;
279021bd5e3SJose Abreu 
280021bd5e3SJose Abreu 	writel(value, ioaddr + XGMAC_DMA_CH_INT_EN(chan));
281d6ddfacdSJose Abreu }
282d6ddfacdSJose Abreu 
dwxgmac2_dma_start_tx(struct stmmac_priv * priv,void __iomem * ioaddr,u32 chan)2831d84b487SAndrew Halaney static void dwxgmac2_dma_start_tx(struct stmmac_priv *priv,
2841d84b487SAndrew Halaney 				  void __iomem *ioaddr, u32 chan)
285d6ddfacdSJose Abreu {
286d6ddfacdSJose Abreu 	u32 value;
287d6ddfacdSJose Abreu 
288d6ddfacdSJose Abreu 	value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));
289d6ddfacdSJose Abreu 	value |= XGMAC_TXST;
290d6ddfacdSJose Abreu 	writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));
291d6ddfacdSJose Abreu 
292d6ddfacdSJose Abreu 	value = readl(ioaddr + XGMAC_TX_CONFIG);
293d6ddfacdSJose Abreu 	value |= XGMAC_CONFIG_TE;
294d6ddfacdSJose Abreu 	writel(value, ioaddr + XGMAC_TX_CONFIG);
295d6ddfacdSJose Abreu }
296d6ddfacdSJose Abreu 
dwxgmac2_dma_stop_tx(struct stmmac_priv * priv,void __iomem * ioaddr,u32 chan)2971d84b487SAndrew Halaney static void dwxgmac2_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
2981d84b487SAndrew Halaney 				 u32 chan)
299d6ddfacdSJose Abreu {
300d6ddfacdSJose Abreu 	u32 value;
301d6ddfacdSJose Abreu 
302d6ddfacdSJose Abreu 	value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));
303d6ddfacdSJose Abreu 	value &= ~XGMAC_TXST;
304d6ddfacdSJose Abreu 	writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));
305d6ddfacdSJose Abreu 
306d6ddfacdSJose Abreu 	value = readl(ioaddr + XGMAC_TX_CONFIG);
307d6ddfacdSJose Abreu 	value &= ~XGMAC_CONFIG_TE;
308d6ddfacdSJose Abreu 	writel(value, ioaddr + XGMAC_TX_CONFIG);
309d6ddfacdSJose Abreu }
310d6ddfacdSJose Abreu 
dwxgmac2_dma_start_rx(struct stmmac_priv * priv,void __iomem * ioaddr,u32 chan)3111d84b487SAndrew Halaney static void dwxgmac2_dma_start_rx(struct stmmac_priv *priv,
3121d84b487SAndrew Halaney 				  void __iomem *ioaddr, u32 chan)
313d6ddfacdSJose Abreu {
314d6ddfacdSJose Abreu 	u32 value;
315d6ddfacdSJose Abreu 
316d6ddfacdSJose Abreu 	value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));
317d6ddfacdSJose Abreu 	value |= XGMAC_RXST;
318d6ddfacdSJose Abreu 	writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));
319d6ddfacdSJose Abreu 
320d6ddfacdSJose Abreu 	value = readl(ioaddr + XGMAC_RX_CONFIG);
321d6ddfacdSJose Abreu 	value |= XGMAC_CONFIG_RE;
322d6ddfacdSJose Abreu 	writel(value, ioaddr + XGMAC_RX_CONFIG);
323d6ddfacdSJose Abreu }
324d6ddfacdSJose Abreu 
dwxgmac2_dma_stop_rx(struct stmmac_priv * priv,void __iomem * ioaddr,u32 chan)3251d84b487SAndrew Halaney static void dwxgmac2_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
3261d84b487SAndrew Halaney 				 u32 chan)
327d6ddfacdSJose Abreu {
328d6ddfacdSJose Abreu 	u32 value;
329d6ddfacdSJose Abreu 
330d6ddfacdSJose Abreu 	value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));
331d6ddfacdSJose Abreu 	value &= ~XGMAC_RXST;
332d6ddfacdSJose Abreu 	writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));
333d6ddfacdSJose Abreu }
334d6ddfacdSJose Abreu 
dwxgmac2_dma_interrupt(struct stmmac_priv * priv,void __iomem * ioaddr,struct stmmac_extra_stats * x,u32 chan,u32 dir)3351d84b487SAndrew Halaney static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv,
3361d84b487SAndrew Halaney 				  void __iomem *ioaddr,
3377e1c520cSOng Boon Leong 				  struct stmmac_extra_stats *x, u32 chan,
3387e1c520cSOng Boon Leong 				  u32 dir)
339d6ddfacdSJose Abreu {
340*9680b2abSPetr Tesarik 	struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);
341d6ddfacdSJose Abreu 	u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(chan));
342fcc509ebSJose Abreu 	u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));
343d6ddfacdSJose Abreu 	int ret = 0;
344d6ddfacdSJose Abreu 
3457e1c520cSOng Boon Leong 	if (dir == DMA_DIR_RX)
3467e1c520cSOng Boon Leong 		intr_status &= XGMAC_DMA_STATUS_MSK_RX;
3477e1c520cSOng Boon Leong 	else if (dir == DMA_DIR_TX)
3487e1c520cSOng Boon Leong 		intr_status &= XGMAC_DMA_STATUS_MSK_TX;
3497e1c520cSOng Boon Leong 
350d6ddfacdSJose Abreu 	/* ABNORMAL interrupts */
351d6ddfacdSJose Abreu 	if (unlikely(intr_status & XGMAC_AIS)) {
35263384883SJose Abreu 		if (unlikely(intr_status & XGMAC_RBU)) {
35363384883SJose Abreu 			x->rx_buf_unav_irq++;
35463384883SJose Abreu 			ret |= handle_rx;
35563384883SJose Abreu 		}
356d6ddfacdSJose Abreu 		if (unlikely(intr_status & XGMAC_TPS)) {
357d6ddfacdSJose Abreu 			x->tx_process_stopped_irq++;
358d6ddfacdSJose Abreu 			ret |= tx_hard_error;
359d6ddfacdSJose Abreu 		}
360d6ddfacdSJose Abreu 		if (unlikely(intr_status & XGMAC_FBE)) {
361d6ddfacdSJose Abreu 			x->fatal_bus_error_irq++;
362d6ddfacdSJose Abreu 			ret |= tx_hard_error;
363d6ddfacdSJose Abreu 		}
364d6ddfacdSJose Abreu 	}
365d6ddfacdSJose Abreu 
366d6ddfacdSJose Abreu 	/* TX/RX NORMAL interrupts */
367d6ddfacdSJose Abreu 	if (likely(intr_status & XGMAC_NIS)) {
368d6ddfacdSJose Abreu 		if (likely(intr_status & XGMAC_RI)) {
369*9680b2abSPetr Tesarik 			u64_stats_update_begin(&stats->syncp);
370*9680b2abSPetr Tesarik 			u64_stats_inc(&stats->rx_normal_irq_n[chan]);
371*9680b2abSPetr Tesarik 			u64_stats_update_end(&stats->syncp);
372d6ddfacdSJose Abreu 			ret |= handle_rx;
373d6ddfacdSJose Abreu 		}
374ae9f346dSJose Abreu 		if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) {
375*9680b2abSPetr Tesarik 			u64_stats_update_begin(&stats->syncp);
376*9680b2abSPetr Tesarik 			u64_stats_inc(&stats->tx_normal_irq_n[chan]);
377*9680b2abSPetr Tesarik 			u64_stats_update_end(&stats->syncp);
378d6ddfacdSJose Abreu 			ret |= handle_tx;
379d6ddfacdSJose Abreu 		}
380d6ddfacdSJose Abreu 	}
381d6ddfacdSJose Abreu 
382d6ddfacdSJose Abreu 	/* Clear interrupts */
383fcc509ebSJose Abreu 	writel(intr_en & intr_status, ioaddr + XGMAC_DMA_CH_STATUS(chan));
384d6ddfacdSJose Abreu 
385d6ddfacdSJose Abreu 	return ret;
386d6ddfacdSJose Abreu }
387d6ddfacdSJose Abreu 
dwxgmac2_get_hw_feature(void __iomem * ioaddr,struct dma_features * dma_cap)388075da584SHerve Codina static int dwxgmac2_get_hw_feature(void __iomem *ioaddr,
389d6ddfacdSJose Abreu 				   struct dma_features *dma_cap)
390d6ddfacdSJose Abreu {
391d6ddfacdSJose Abreu 	u32 hw_cap;
392d6ddfacdSJose Abreu 
393d6ddfacdSJose Abreu 	/* MAC HW feature 0 */
394d6ddfacdSJose Abreu 	hw_cap = readl(ioaddr + XGMAC_HW_FEATURE0);
395669a5556SFurong Xu 	dma_cap->edma = (hw_cap & XGMAC_HWFEAT_EDMA) >> 31;
396669a5556SFurong Xu 	dma_cap->ediffc = (hw_cap & XGMAC_HWFEAT_EDIFFC) >> 30;
397669a5556SFurong Xu 	dma_cap->vxn = (hw_cap & XGMAC_HWFEAT_VXN) >> 29;
39830d93227SJose Abreu 	dma_cap->vlins = (hw_cap & XGMAC_HWFEAT_SAVLANINS) >> 27;
39958c1e0baSFurong Xu 	dma_cap->tssrc = (hw_cap & XGMAC_HWFEAT_TSSTSSEL) >> 25;
40058c1e0baSFurong Xu 	dma_cap->multi_addr = (hw_cap & XGMAC_HWFEAT_ADDMACADRSEL) >> 18;
401d6ddfacdSJose Abreu 	dma_cap->rx_coe = (hw_cap & XGMAC_HWFEAT_RXCOESEL) >> 16;
402d6ddfacdSJose Abreu 	dma_cap->tx_coe = (hw_cap & XGMAC_HWFEAT_TXCOESEL) >> 14;
40381b945aeSJose Abreu 	dma_cap->eee = (hw_cap & XGMAC_HWFEAT_EEESEL) >> 13;
404d6ddfacdSJose Abreu 	dma_cap->atime_stamp = (hw_cap & XGMAC_HWFEAT_TSSEL) >> 12;
405d6ddfacdSJose Abreu 	dma_cap->av = (hw_cap & XGMAC_HWFEAT_AVSEL) >> 11;
40608c1ac3bSJose Abreu 	dma_cap->av &= !((hw_cap & XGMAC_HWFEAT_RAVSEL) >> 10);
4075904a980SJose Abreu 	dma_cap->arpoffsel = (hw_cap & XGMAC_HWFEAT_ARPOFFSEL) >> 9;
408b6cdf09fSJose Abreu 	dma_cap->rmon = (hw_cap & XGMAC_HWFEAT_MMCSEL) >> 8;
409d6ddfacdSJose Abreu 	dma_cap->pmt_magic_frame = (hw_cap & XGMAC_HWFEAT_MGKSEL) >> 7;
410d6ddfacdSJose Abreu 	dma_cap->pmt_remote_wake_up = (hw_cap & XGMAC_HWFEAT_RWKSEL) >> 6;
41158c1e0baSFurong Xu 	dma_cap->sma_mdio = (hw_cap & XGMAC_HWFEAT_SMASEL) >> 5;
4123cd1cfcbSJose Abreu 	dma_cap->vlhash = (hw_cap & XGMAC_HWFEAT_VLHASH) >> 4;
41358c1e0baSFurong Xu 	dma_cap->half_duplex = (hw_cap & XGMAC_HWFEAT_HDSEL) >> 3;
414d6ddfacdSJose Abreu 	dma_cap->mbps_1000 = (hw_cap & XGMAC_HWFEAT_GMIISEL) >> 1;
415d6ddfacdSJose Abreu 
416d6ddfacdSJose Abreu 	/* MAC HW feature 1 */
417d6ddfacdSJose Abreu 	hw_cap = readl(ioaddr + XGMAC_HW_FEATURE1);
418425eabddSJose Abreu 	dma_cap->l3l4fnum = (hw_cap & XGMAC_HWFEAT_L3L4FNUM) >> 27;
41947448ff2SRohan G Thomas 	/* If L3L4FNUM < 8, then the number of L3L4 filters supported by
42047448ff2SRohan G Thomas 	 * XGMAC is equal to L3L4FNUM. From L3L4FNUM >= 8 the number of
42147448ff2SRohan G Thomas 	 * L3L4 filters goes on like 8, 16, 32, ... Current maximum of
42247448ff2SRohan G Thomas 	 * L3L4FNUM = 10.
42347448ff2SRohan G Thomas 	 */
42447448ff2SRohan G Thomas 	if (dma_cap->l3l4fnum >= 8 && dma_cap->l3l4fnum <= 10)
42547448ff2SRohan G Thomas 		dma_cap->l3l4fnum = 8 << (dma_cap->l3l4fnum - 8);
42647448ff2SRohan G Thomas 	else if (dma_cap->l3l4fnum > 10)
42747448ff2SRohan G Thomas 		dma_cap->l3l4fnum = 32;
42847448ff2SRohan G Thomas 
429c11986b9SJose Abreu 	dma_cap->hash_tb_sz = (hw_cap & XGMAC_HWFEAT_HASHTBLSZ) >> 24;
430669a5556SFurong Xu 	dma_cap->numtc = ((hw_cap & XGMAC_HWFEAT_NUMTC) >> 21) + 1;
43176067459SJose Abreu 	dma_cap->rssen = (hw_cap & XGMAC_HWFEAT_RSSEN) >> 20;
432669a5556SFurong Xu 	dma_cap->dbgmem = (hw_cap & XGMAC_HWFEAT_DBGMEMA) >> 19;
433d6ddfacdSJose Abreu 	dma_cap->tsoen = (hw_cap & XGMAC_HWFEAT_TSOEN) >> 18;
43467afd6d1SJose Abreu 	dma_cap->sphen = (hw_cap & XGMAC_HWFEAT_SPHEN) >> 17;
435669a5556SFurong Xu 	dma_cap->dcben = (hw_cap & XGMAC_HWFEAT_DCBEN) >> 16;
436a993db88SJose Abreu 
437a993db88SJose Abreu 	dma_cap->addr64 = (hw_cap & XGMAC_HWFEAT_ADDR64) >> 14;
438a993db88SJose Abreu 	switch (dma_cap->addr64) {
439a993db88SJose Abreu 	case 0:
440a993db88SJose Abreu 		dma_cap->addr64 = 32;
441a993db88SJose Abreu 		break;
442a993db88SJose Abreu 	case 1:
443a993db88SJose Abreu 		dma_cap->addr64 = 40;
444a993db88SJose Abreu 		break;
445a993db88SJose Abreu 	case 2:
446a993db88SJose Abreu 		dma_cap->addr64 = 48;
447a993db88SJose Abreu 		break;
448a993db88SJose Abreu 	default:
449a993db88SJose Abreu 		dma_cap->addr64 = 32;
450a993db88SJose Abreu 		break;
451a993db88SJose Abreu 	}
452a993db88SJose Abreu 
453669a5556SFurong Xu 	dma_cap->advthword = (hw_cap & XGMAC_HWFEAT_ADVTHWORD) >> 13;
454669a5556SFurong Xu 	dma_cap->ptoen = (hw_cap & XGMAC_HWFEAT_PTOEN) >> 12;
455669a5556SFurong Xu 	dma_cap->osten = (hw_cap & XGMAC_HWFEAT_OSTEN) >> 11;
456d6ddfacdSJose Abreu 	dma_cap->tx_fifo_size =
457d6ddfacdSJose Abreu 		128 << ((hw_cap & XGMAC_HWFEAT_TXFIFOSIZE) >> 6);
458669a5556SFurong Xu 	dma_cap->pfcen = (hw_cap & XGMAC_HWFEAT_PFCEN) >> 5;
459d6ddfacdSJose Abreu 	dma_cap->rx_fifo_size =
460d6ddfacdSJose Abreu 		128 << ((hw_cap & XGMAC_HWFEAT_RXFIFOSIZE) >> 0);
461d6ddfacdSJose Abreu 
462d6ddfacdSJose Abreu 	/* MAC HW feature 2 */
463d6ddfacdSJose Abreu 	hw_cap = readl(ioaddr + XGMAC_HW_FEATURE2);
464669a5556SFurong Xu 	dma_cap->aux_snapshot_n = (hw_cap & XGMAC_HWFEAT_AUXSNAPNUM) >> 28;
465d6ddfacdSJose Abreu 	dma_cap->pps_out_num = (hw_cap & XGMAC_HWFEAT_PPSOUTNUM) >> 24;
466d6ddfacdSJose Abreu 	dma_cap->number_tx_channel =
467d6ddfacdSJose Abreu 		((hw_cap & XGMAC_HWFEAT_TXCHCNT) >> 18) + 1;
468d6ddfacdSJose Abreu 	dma_cap->number_rx_channel =
469d6ddfacdSJose Abreu 		((hw_cap & XGMAC_HWFEAT_RXCHCNT) >> 12) + 1;
470d6ddfacdSJose Abreu 	dma_cap->number_tx_queues =
471d6ddfacdSJose Abreu 		((hw_cap & XGMAC_HWFEAT_TXQCNT) >> 6) + 1;
472d6ddfacdSJose Abreu 	dma_cap->number_rx_queues =
473d6ddfacdSJose Abreu 		((hw_cap & XGMAC_HWFEAT_RXQCNT) >> 0) + 1;
47456e58d6cSJose Abreu 
47556e58d6cSJose Abreu 	/* MAC HW feature 3 */
47656e58d6cSJose Abreu 	hw_cap = readl(ioaddr + XGMAC_HW_FEATURE3);
477669a5556SFurong Xu 	dma_cap->tbs_ch_num = ((hw_cap & XGMAC_HWFEAT_TBSCH) >> 28) + 1;
4786a549b9fSJose Abreu 	dma_cap->tbssel = (hw_cap & XGMAC_HWFEAT_TBSSEL) >> 27;
479f0e56c8dSJose Abreu 	dma_cap->fpesel = (hw_cap & XGMAC_HWFEAT_FPESEL) >> 26;
480669a5556SFurong Xu 	dma_cap->sgfsel = (hw_cap & XGMAC_HWFEAT_SGFSEL) >> 25;
4818572aec3SJose Abreu 	dma_cap->estwid = (hw_cap & XGMAC_HWFEAT_ESTWID) >> 23;
4828572aec3SJose Abreu 	dma_cap->estdep = (hw_cap & XGMAC_HWFEAT_ESTDEP) >> 20;
4838572aec3SJose Abreu 	dma_cap->estsel = (hw_cap & XGMAC_HWFEAT_ESTSEL) >> 19;
484669a5556SFurong Xu 	dma_cap->ttsfd = (hw_cap & XGMAC_HWFEAT_TTSFD) >> 16;
48556e58d6cSJose Abreu 	dma_cap->asp = (hw_cap & XGMAC_HWFEAT_ASP) >> 14;
48630d93227SJose Abreu 	dma_cap->dvlan = (hw_cap & XGMAC_HWFEAT_DVLAN) >> 13;
487d6e1c12cSJose Abreu 	dma_cap->frpes = (hw_cap & XGMAC_HWFEAT_FRPES) >> 11;
488d6e1c12cSJose Abreu 	dma_cap->frpbs = (hw_cap & XGMAC_HWFEAT_FRPPB) >> 9;
489669a5556SFurong Xu 	dma_cap->pou_ost_en = (hw_cap & XGMAC_HWFEAT_POUOST) >> 8;
490669a5556SFurong Xu 	dma_cap->frppipe_num = ((hw_cap & XGMAC_HWFEAT_FRPPIPE) >> 5) + 1;
491669a5556SFurong Xu 	dma_cap->cbtisel = (hw_cap & XGMAC_HWFEAT_CBTISEL) >> 4;
492d6e1c12cSJose Abreu 	dma_cap->frpsel = (hw_cap & XGMAC_HWFEAT_FRPSEL) >> 3;
493669a5556SFurong Xu 	dma_cap->nrvf_num = (hw_cap & XGMAC_HWFEAT_NRVF) >> 0;
494669a5556SFurong Xu 
495669a5556SFurong Xu 	/* MAC HW feature 4 */
496669a5556SFurong Xu 	hw_cap = readl(ioaddr + XGMAC_HW_FEATURE4);
497669a5556SFurong Xu 	dma_cap->asp |= (hw_cap & XGMAC_HWFEAT_EASP) >> 2;
498669a5556SFurong Xu 	dma_cap->pcsel = (hw_cap & XGMAC_HWFEAT_PCSEL) >> 0;
499075da584SHerve Codina 
500075da584SHerve Codina 	return 0;
501d6ddfacdSJose Abreu }
502d6ddfacdSJose Abreu 
dwxgmac2_rx_watchdog(struct stmmac_priv * priv,void __iomem * ioaddr,u32 riwt,u32 queue)5031d84b487SAndrew Halaney static void dwxgmac2_rx_watchdog(struct stmmac_priv *priv, void __iomem *ioaddr,
5041d84b487SAndrew Halaney 				 u32 riwt, u32 queue)
505d6ddfacdSJose Abreu {
506db2f2842SOng Boon Leong 	writel(riwt & XGMAC_RWT, ioaddr + XGMAC_DMA_CH_Rx_WATCHDOG(queue));
507d6ddfacdSJose Abreu }
508d6ddfacdSJose Abreu 
dwxgmac2_set_rx_ring_len(struct stmmac_priv * priv,void __iomem * ioaddr,u32 len,u32 chan)5091d84b487SAndrew Halaney static void dwxgmac2_set_rx_ring_len(struct stmmac_priv *priv,
5101d84b487SAndrew Halaney 				     void __iomem *ioaddr, u32 len, u32 chan)
511d6ddfacdSJose Abreu {
512d6ddfacdSJose Abreu 	writel(len, ioaddr + XGMAC_DMA_CH_RxDESC_RING_LEN(chan));
513d6ddfacdSJose Abreu }
514d6ddfacdSJose Abreu 
dwxgmac2_set_tx_ring_len(struct stmmac_priv * priv,void __iomem * ioaddr,u32 len,u32 chan)5151d84b487SAndrew Halaney static void dwxgmac2_set_tx_ring_len(struct stmmac_priv *priv,
5161d84b487SAndrew Halaney 				     void __iomem *ioaddr, u32 len, u32 chan)
517d6ddfacdSJose Abreu {
518d6ddfacdSJose Abreu 	writel(len, ioaddr + XGMAC_DMA_CH_TxDESC_RING_LEN(chan));
519d6ddfacdSJose Abreu }
520d6ddfacdSJose Abreu 
dwxgmac2_set_rx_tail_ptr(struct stmmac_priv * priv,void __iomem * ioaddr,u32 ptr,u32 chan)5211d84b487SAndrew Halaney static void dwxgmac2_set_rx_tail_ptr(struct stmmac_priv *priv,
5221d84b487SAndrew Halaney 				     void __iomem *ioaddr, u32 ptr, u32 chan)
523d6ddfacdSJose Abreu {
524d6ddfacdSJose Abreu 	writel(ptr, ioaddr + XGMAC_DMA_CH_RxDESC_TAIL_LPTR(chan));
525d6ddfacdSJose Abreu }
526d6ddfacdSJose Abreu 
dwxgmac2_set_tx_tail_ptr(struct stmmac_priv * priv,void __iomem * ioaddr,u32 ptr,u32 chan)5271d84b487SAndrew Halaney static void dwxgmac2_set_tx_tail_ptr(struct stmmac_priv *priv,
5281d84b487SAndrew Halaney 				     void __iomem *ioaddr, u32 ptr, u32 chan)
529d6ddfacdSJose Abreu {
530d6ddfacdSJose Abreu 	writel(ptr, ioaddr + XGMAC_DMA_CH_TxDESC_TAIL_LPTR(chan));
531d6ddfacdSJose Abreu }
532d6ddfacdSJose Abreu 
dwxgmac2_enable_tso(struct stmmac_priv * priv,void __iomem * ioaddr,bool en,u32 chan)5331d84b487SAndrew Halaney static void dwxgmac2_enable_tso(struct stmmac_priv *priv, void __iomem *ioaddr,
5341d84b487SAndrew Halaney 				bool en, u32 chan)
535d6ddfacdSJose Abreu {
536d6ddfacdSJose Abreu 	u32 value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));
537d6ddfacdSJose Abreu 
538d6ddfacdSJose Abreu 	if (en)
539d6ddfacdSJose Abreu 		value |= XGMAC_TSE;
540d6ddfacdSJose Abreu 	else
541d6ddfacdSJose Abreu 		value &= ~XGMAC_TSE;
542d6ddfacdSJose Abreu 
543d6ddfacdSJose Abreu 	writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));
544d6ddfacdSJose Abreu }
545d6ddfacdSJose Abreu 
dwxgmac2_qmode(struct stmmac_priv * priv,void __iomem * ioaddr,u32 channel,u8 qmode)5461d84b487SAndrew Halaney static void dwxgmac2_qmode(struct stmmac_priv *priv, void __iomem *ioaddr,
5471d84b487SAndrew Halaney 			   u32 channel, u8 qmode)
548ec6ea8e3SJose Abreu {
549ec6ea8e3SJose Abreu 	u32 value = readl(ioaddr + XGMAC_MTL_TXQ_OPMODE(channel));
550132f2f20SJose Abreu 	u32 flow = readl(ioaddr + XGMAC_RX_FLOW_CTRL);
551ec6ea8e3SJose Abreu 
552ec6ea8e3SJose Abreu 	value &= ~XGMAC_TXQEN;
553ec6ea8e3SJose Abreu 	if (qmode != MTL_QUEUE_AVB) {
554ec6ea8e3SJose Abreu 		value |= 0x2 << XGMAC_TXQEN_SHIFT;
555ec6ea8e3SJose Abreu 		writel(0, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(channel));
556ec6ea8e3SJose Abreu 	} else {
557ec6ea8e3SJose Abreu 		value |= 0x1 << XGMAC_TXQEN_SHIFT;
558132f2f20SJose Abreu 		writel(flow & (~XGMAC_RFE), ioaddr + XGMAC_RX_FLOW_CTRL);
559ec6ea8e3SJose Abreu 	}
560ec6ea8e3SJose Abreu 
561ec6ea8e3SJose Abreu 	writel(value, ioaddr +  XGMAC_MTL_TXQ_OPMODE(channel));
562ec6ea8e3SJose Abreu }
563ec6ea8e3SJose Abreu 
dwxgmac2_set_bfsize(struct stmmac_priv * priv,void __iomem * ioaddr,int bfsize,u32 chan)5641d84b487SAndrew Halaney static void dwxgmac2_set_bfsize(struct stmmac_priv *priv, void __iomem *ioaddr,
5651d84b487SAndrew Halaney 				int bfsize, u32 chan)
566d6ddfacdSJose Abreu {
567d6ddfacdSJose Abreu 	u32 value;
568d6ddfacdSJose Abreu 
569d6ddfacdSJose Abreu 	value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));
57011d55fd9SJose Abreu 	value &= ~XGMAC_RBSZ;
57111d55fd9SJose Abreu 	value |= bfsize << XGMAC_RBSZ_SHIFT;
572d6ddfacdSJose Abreu 	writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));
573d6ddfacdSJose Abreu }
574d6ddfacdSJose Abreu 
dwxgmac2_enable_sph(struct stmmac_priv * priv,void __iomem * ioaddr,bool en,u32 chan)5751d84b487SAndrew Halaney static void dwxgmac2_enable_sph(struct stmmac_priv *priv, void __iomem *ioaddr,
5761d84b487SAndrew Halaney 				bool en, u32 chan)
57767afd6d1SJose Abreu {
57867afd6d1SJose Abreu 	u32 value = readl(ioaddr + XGMAC_RX_CONFIG);
57967afd6d1SJose Abreu 
58067afd6d1SJose Abreu 	value &= ~XGMAC_CONFIG_HDSMS;
58167afd6d1SJose Abreu 	value |= XGMAC_CONFIG_HDSMS_256; /* Segment max 256 bytes */
58267afd6d1SJose Abreu 	writel(value, ioaddr + XGMAC_RX_CONFIG);
58367afd6d1SJose Abreu 
58467afd6d1SJose Abreu 	value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(chan));
58567afd6d1SJose Abreu 	if (en)
58667afd6d1SJose Abreu 		value |= XGMAC_SPH;
58767afd6d1SJose Abreu 	else
58867afd6d1SJose Abreu 		value &= ~XGMAC_SPH;
58967afd6d1SJose Abreu 	writel(value, ioaddr + XGMAC_DMA_CH_CONTROL(chan));
59067afd6d1SJose Abreu }
59167afd6d1SJose Abreu 
dwxgmac2_enable_tbs(struct stmmac_priv * priv,void __iomem * ioaddr,bool en,u32 chan)5921d84b487SAndrew Halaney static int dwxgmac2_enable_tbs(struct stmmac_priv *priv, void __iomem *ioaddr,
5931d84b487SAndrew Halaney 			       bool en, u32 chan)
5946a549b9fSJose Abreu {
5956a549b9fSJose Abreu 	u32 value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));
5966a549b9fSJose Abreu 
5976a549b9fSJose Abreu 	if (en)
5986a549b9fSJose Abreu 		value |= XGMAC_EDSE;
5996a549b9fSJose Abreu 	else
6006a549b9fSJose Abreu 		value &= ~XGMAC_EDSE;
6016a549b9fSJose Abreu 
6026a549b9fSJose Abreu 	writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));
6036a549b9fSJose Abreu 
6046a549b9fSJose Abreu 	value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)) & XGMAC_EDSE;
6056a549b9fSJose Abreu 	if (en && !value)
6066a549b9fSJose Abreu 		return -EIO;
6076a549b9fSJose Abreu 
6086a549b9fSJose Abreu 	writel(XGMAC_DEF_FTOS, ioaddr + XGMAC_DMA_TBS_CTRL0);
6096a549b9fSJose Abreu 	writel(XGMAC_DEF_FTOS, ioaddr + XGMAC_DMA_TBS_CTRL1);
6106a549b9fSJose Abreu 	writel(XGMAC_DEF_FTOS, ioaddr + XGMAC_DMA_TBS_CTRL2);
6116a549b9fSJose Abreu 	writel(XGMAC_DEF_FTOS, ioaddr + XGMAC_DMA_TBS_CTRL3);
6126a549b9fSJose Abreu 	return 0;
6136a549b9fSJose Abreu }
6146a549b9fSJose Abreu 
615d6ddfacdSJose Abreu const struct stmmac_dma_ops dwxgmac210_dma_ops = {
616d6ddfacdSJose Abreu 	.reset = dwxgmac2_dma_reset,
617d6ddfacdSJose Abreu 	.init = dwxgmac2_dma_init,
618d6ddfacdSJose Abreu 	.init_chan = dwxgmac2_dma_init_chan,
619d6ddfacdSJose Abreu 	.init_rx_chan = dwxgmac2_dma_init_rx_chan,
620d6ddfacdSJose Abreu 	.init_tx_chan = dwxgmac2_dma_init_tx_chan,
621d6ddfacdSJose Abreu 	.axi = dwxgmac2_dma_axi,
622bfc56530SJose Abreu 	.dump_regs = dwxgmac2_dma_dump_regs,
623d6ddfacdSJose Abreu 	.dma_rx_mode = dwxgmac2_dma_rx_mode,
624d6ddfacdSJose Abreu 	.dma_tx_mode = dwxgmac2_dma_tx_mode,
625d6ddfacdSJose Abreu 	.enable_dma_irq = dwxgmac2_enable_dma_irq,
626d6ddfacdSJose Abreu 	.disable_dma_irq = dwxgmac2_disable_dma_irq,
627d6ddfacdSJose Abreu 	.start_tx = dwxgmac2_dma_start_tx,
628d6ddfacdSJose Abreu 	.stop_tx = dwxgmac2_dma_stop_tx,
629d6ddfacdSJose Abreu 	.start_rx = dwxgmac2_dma_start_rx,
630d6ddfacdSJose Abreu 	.stop_rx = dwxgmac2_dma_stop_rx,
631d6ddfacdSJose Abreu 	.dma_interrupt = dwxgmac2_dma_interrupt,
632d6ddfacdSJose Abreu 	.get_hw_feature = dwxgmac2_get_hw_feature,
633d6ddfacdSJose Abreu 	.rx_watchdog = dwxgmac2_rx_watchdog,
634d6ddfacdSJose Abreu 	.set_rx_ring_len = dwxgmac2_set_rx_ring_len,
635d6ddfacdSJose Abreu 	.set_tx_ring_len = dwxgmac2_set_tx_ring_len,
636d6ddfacdSJose Abreu 	.set_rx_tail_ptr = dwxgmac2_set_rx_tail_ptr,
637d6ddfacdSJose Abreu 	.set_tx_tail_ptr = dwxgmac2_set_tx_tail_ptr,
638d6ddfacdSJose Abreu 	.enable_tso = dwxgmac2_enable_tso,
639ec6ea8e3SJose Abreu 	.qmode = dwxgmac2_qmode,
640d6ddfacdSJose Abreu 	.set_bfsize = dwxgmac2_set_bfsize,
64167afd6d1SJose Abreu 	.enable_sph = dwxgmac2_enable_sph,
6426a549b9fSJose Abreu 	.enable_tbs = dwxgmac2_enable_tbs,
643d6ddfacdSJose Abreu };
644