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