brintos

brintos / linux-shallow public Read only

0
0
Text · 18.2 KiB · 7840bc4 Raw
644 lines · c
1// SPDX-License-Identifier: (GPL-2.0 OR MIT)2/*3 * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates.4 * stmmac XGMAC support.5 */6 7#include <linux/iopoll.h>8#include "stmmac.h"9#include "dwxgmac2.h"10 11static int dwxgmac2_dma_reset(void __iomem *ioaddr)12{13	u32 value = readl(ioaddr + XGMAC_DMA_MODE);14 15	/* DMA SW reset */16	writel(value | XGMAC_SWR, ioaddr + XGMAC_DMA_MODE);17 18	return readl_poll_timeout(ioaddr + XGMAC_DMA_MODE, value,19				  !(value & XGMAC_SWR), 0, 100000);20}21 22static void dwxgmac2_dma_init(void __iomem *ioaddr,23			      struct stmmac_dma_cfg *dma_cfg)24{25	u32 value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);26 27	if (dma_cfg->aal)28		value |= XGMAC_AAL;29 30	if (dma_cfg->eame)31		value |= XGMAC_EAME;32 33	writel(value, ioaddr + XGMAC_DMA_SYSBUS_MODE);34}35 36static void dwxgmac2_dma_init_chan(struct stmmac_priv *priv,37				   void __iomem *ioaddr,38				   struct stmmac_dma_cfg *dma_cfg, u32 chan)39{40	u32 value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(chan));41 42	if (dma_cfg->pblx8)43		value |= XGMAC_PBLx8;44 45	writel(value, ioaddr + XGMAC_DMA_CH_CONTROL(chan));46	writel(XGMAC_DMA_INT_DEFAULT_EN, ioaddr + XGMAC_DMA_CH_INT_EN(chan));47}48 49static void dwxgmac2_dma_init_rx_chan(struct stmmac_priv *priv,50				      void __iomem *ioaddr,51				      struct stmmac_dma_cfg *dma_cfg,52				      dma_addr_t phy, u32 chan)53{54	u32 rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;55	u32 value;56 57	value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));58	value &= ~XGMAC_RxPBL;59	value |= (rxpbl << XGMAC_RxPBL_SHIFT) & XGMAC_RxPBL;60	writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));61 62	writel(upper_32_bits(phy), ioaddr + XGMAC_DMA_CH_RxDESC_HADDR(chan));63	writel(lower_32_bits(phy), ioaddr + XGMAC_DMA_CH_RxDESC_LADDR(chan));64}65 66static void dwxgmac2_dma_init_tx_chan(struct stmmac_priv *priv,67				      void __iomem *ioaddr,68				      struct stmmac_dma_cfg *dma_cfg,69				      dma_addr_t phy, u32 chan)70{71	u32 txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;72	u32 value;73 74	value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));75	value &= ~XGMAC_TxPBL;76	value |= (txpbl << XGMAC_TxPBL_SHIFT) & XGMAC_TxPBL;77	value |= XGMAC_OSP;78	writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));79 80	writel(upper_32_bits(phy), ioaddr + XGMAC_DMA_CH_TxDESC_HADDR(chan));81	writel(lower_32_bits(phy), ioaddr + XGMAC_DMA_CH_TxDESC_LADDR(chan));82}83 84static void dwxgmac2_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)85{86	u32 value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE);87	int i;88 89	if (axi->axi_lpi_en)90		value |= XGMAC_EN_LPI;91	if (axi->axi_xit_frm)92		value |= XGMAC_LPI_XIT_PKT;93 94	value &= ~XGMAC_WR_OSR_LMT;95	value |= (axi->axi_wr_osr_lmt << XGMAC_WR_OSR_LMT_SHIFT) &96		XGMAC_WR_OSR_LMT;97 98	value &= ~XGMAC_RD_OSR_LMT;99	value |= (axi->axi_rd_osr_lmt << XGMAC_RD_OSR_LMT_SHIFT) &100		XGMAC_RD_OSR_LMT;101 102	if (!axi->axi_fb)103		value |= XGMAC_UNDEF;104 105	value &= ~XGMAC_BLEN;106	for (i = 0; i < AXI_BLEN; i++) {107		switch (axi->axi_blen[i]) {108		case 256:109			value |= XGMAC_BLEN256;110			break;111		case 128:112			value |= XGMAC_BLEN128;113			break;114		case 64:115			value |= XGMAC_BLEN64;116			break;117		case 32:118			value |= XGMAC_BLEN32;119			break;120		case 16:121			value |= XGMAC_BLEN16;122			break;123		case 8:124			value |= XGMAC_BLEN8;125			break;126		case 4:127			value |= XGMAC_BLEN4;128			break;129		}130	}131 132	writel(value, ioaddr + XGMAC_DMA_SYSBUS_MODE);133	writel(XGMAC_TDPS, ioaddr + XGMAC_TX_EDMA_CTRL);134	writel(XGMAC_RDPS, ioaddr + XGMAC_RX_EDMA_CTRL);135}136 137static void dwxgmac2_dma_dump_regs(struct stmmac_priv *priv,138				   void __iomem *ioaddr, u32 *reg_space)139{140	int i;141 142	for (i = (XGMAC_DMA_MODE / 4); i < XGMAC_REGSIZE; i++)143		reg_space[i] = readl(ioaddr + i * 4);144}145 146static void dwxgmac2_dma_rx_mode(struct stmmac_priv *priv, void __iomem *ioaddr,147				 int mode, u32 channel, int fifosz, u8 qmode)148{149	u32 value = readl(ioaddr + XGMAC_MTL_RXQ_OPMODE(channel));150	unsigned int rqs = fifosz / 256 - 1;151 152	if (mode == SF_DMA_MODE) {153		value |= XGMAC_RSF;154	} else {155		value &= ~XGMAC_RSF;156		value &= ~XGMAC_RTC;157 158		if (mode <= 64)159			value |= 0x0 << XGMAC_RTC_SHIFT;160		else if (mode <= 96)161			value |= 0x2 << XGMAC_RTC_SHIFT;162		else163			value |= 0x3 << XGMAC_RTC_SHIFT;164	}165 166	value &= ~XGMAC_RQS;167	value |= (rqs << XGMAC_RQS_SHIFT) & XGMAC_RQS;168 169	if ((fifosz >= 4096) && (qmode != MTL_QUEUE_AVB)) {170		u32 flow = readl(ioaddr + XGMAC_MTL_RXQ_FLOW_CONTROL(channel));171		unsigned int rfd, rfa;172 173		value |= XGMAC_EHFC;174 175		/* Set Threshold for Activating Flow Control to min 2 frames,176		 * i.e. 1500 * 2 = 3000 bytes.177		 *178		 * Set Threshold for Deactivating Flow Control to min 1 frame,179		 * i.e. 1500 bytes.180		 */181		switch (fifosz) {182		case 4096:183			/* This violates the above formula because of FIFO size184			 * limit therefore overflow may occur in spite of this.185			 */186			rfd = 0x03; /* Full-2.5K */187			rfa = 0x01; /* Full-1.5K */188			break;189 190		default:191			rfd = 0x07; /* Full-4.5K */192			rfa = 0x04; /* Full-3K */193			break;194		}195 196		flow &= ~XGMAC_RFD;197		flow |= rfd << XGMAC_RFD_SHIFT;198 199		flow &= ~XGMAC_RFA;200		flow |= rfa << XGMAC_RFA_SHIFT;201 202		writel(flow, ioaddr + XGMAC_MTL_RXQ_FLOW_CONTROL(channel));203	}204 205	writel(value, ioaddr + XGMAC_MTL_RXQ_OPMODE(channel));206 207	/* Enable MTL RX overflow */208	value = readl(ioaddr + XGMAC_MTL_QINTEN(channel));209	writel(value | XGMAC_RXOIE, ioaddr + XGMAC_MTL_QINTEN(channel));210}211 212static void dwxgmac2_dma_tx_mode(struct stmmac_priv *priv, void __iomem *ioaddr,213				 int mode, u32 channel, int fifosz, u8 qmode)214{215	u32 value = readl(ioaddr + XGMAC_MTL_TXQ_OPMODE(channel));216	unsigned int tqs = fifosz / 256 - 1;217 218	if (mode == SF_DMA_MODE) {219		value |= XGMAC_TSF;220	} else {221		value &= ~XGMAC_TSF;222		value &= ~XGMAC_TTC;223 224		if (mode <= 64)225			value |= 0x0 << XGMAC_TTC_SHIFT;226		else if (mode <= 96)227			value |= 0x2 << XGMAC_TTC_SHIFT;228		else if (mode <= 128)229			value |= 0x3 << XGMAC_TTC_SHIFT;230		else if (mode <= 192)231			value |= 0x4 << XGMAC_TTC_SHIFT;232		else if (mode <= 256)233			value |= 0x5 << XGMAC_TTC_SHIFT;234		else if (mode <= 384)235			value |= 0x6 << XGMAC_TTC_SHIFT;236		else237			value |= 0x7 << XGMAC_TTC_SHIFT;238	}239 240	/* Use static TC to Queue mapping */241	value |= (channel << XGMAC_Q2TCMAP_SHIFT) & XGMAC_Q2TCMAP;242 243	value &= ~XGMAC_TXQEN;244	if (qmode != MTL_QUEUE_AVB)245		value |= 0x2 << XGMAC_TXQEN_SHIFT;246	else247		value |= 0x1 << XGMAC_TXQEN_SHIFT;248 249	value &= ~XGMAC_TQS;250	value |= (tqs << XGMAC_TQS_SHIFT) & XGMAC_TQS;251 252	writel(value, ioaddr +  XGMAC_MTL_TXQ_OPMODE(channel));253}254 255static void dwxgmac2_enable_dma_irq(struct stmmac_priv *priv,256				    void __iomem *ioaddr, u32 chan,257				    bool rx, bool tx)258{259	u32 value = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));260 261	if (rx)262		value |= XGMAC_DMA_INT_DEFAULT_RX;263	if (tx)264		value |= XGMAC_DMA_INT_DEFAULT_TX;265 266	writel(value, ioaddr + XGMAC_DMA_CH_INT_EN(chan));267}268 269static void dwxgmac2_disable_dma_irq(struct stmmac_priv *priv,270				     void __iomem *ioaddr, u32 chan,271				     bool rx, bool tx)272{273	u32 value = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));274 275	if (rx)276		value &= ~XGMAC_DMA_INT_DEFAULT_RX;277	if (tx)278		value &= ~XGMAC_DMA_INT_DEFAULT_TX;279 280	writel(value, ioaddr + XGMAC_DMA_CH_INT_EN(chan));281}282 283static void dwxgmac2_dma_start_tx(struct stmmac_priv *priv,284				  void __iomem *ioaddr, u32 chan)285{286	u32 value;287 288	value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));289	value |= XGMAC_TXST;290	writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));291 292	value = readl(ioaddr + XGMAC_TX_CONFIG);293	value |= XGMAC_CONFIG_TE;294	writel(value, ioaddr + XGMAC_TX_CONFIG);295}296 297static void dwxgmac2_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr,298				 u32 chan)299{300	u32 value;301 302	value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));303	value &= ~XGMAC_TXST;304	writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));305 306	value = readl(ioaddr + XGMAC_TX_CONFIG);307	value &= ~XGMAC_CONFIG_TE;308	writel(value, ioaddr + XGMAC_TX_CONFIG);309}310 311static void dwxgmac2_dma_start_rx(struct stmmac_priv *priv,312				  void __iomem *ioaddr, u32 chan)313{314	u32 value;315 316	value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));317	value |= XGMAC_RXST;318	writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));319 320	value = readl(ioaddr + XGMAC_RX_CONFIG);321	value |= XGMAC_CONFIG_RE;322	writel(value, ioaddr + XGMAC_RX_CONFIG);323}324 325static void dwxgmac2_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr,326				 u32 chan)327{328	u32 value;329 330	value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));331	value &= ~XGMAC_RXST;332	writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));333}334 335static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv,336				  void __iomem *ioaddr,337				  struct stmmac_extra_stats *x, u32 chan,338				  u32 dir)339{340	struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);341	u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(chan));342	u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));343	int ret = 0;344 345	if (dir == DMA_DIR_RX)346		intr_status &= XGMAC_DMA_STATUS_MSK_RX;347	else if (dir == DMA_DIR_TX)348		intr_status &= XGMAC_DMA_STATUS_MSK_TX;349 350	/* ABNORMAL interrupts */351	if (unlikely(intr_status & XGMAC_AIS)) {352		if (unlikely(intr_status & XGMAC_RBU)) {353			x->rx_buf_unav_irq++;354			ret |= handle_rx;355		}356		if (unlikely(intr_status & XGMAC_TPS)) {357			x->tx_process_stopped_irq++;358			ret |= tx_hard_error;359		}360		if (unlikely(intr_status & XGMAC_FBE)) {361			x->fatal_bus_error_irq++;362			ret |= tx_hard_error;363		}364	}365 366	/* TX/RX NORMAL interrupts */367	if (likely(intr_status & XGMAC_NIS)) {368		if (likely(intr_status & XGMAC_RI)) {369			u64_stats_update_begin(&stats->syncp);370			u64_stats_inc(&stats->rx_normal_irq_n[chan]);371			u64_stats_update_end(&stats->syncp);372			ret |= handle_rx;373		}374		if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) {375			u64_stats_update_begin(&stats->syncp);376			u64_stats_inc(&stats->tx_normal_irq_n[chan]);377			u64_stats_update_end(&stats->syncp);378			ret |= handle_tx;379		}380	}381 382	/* Clear interrupts */383	writel(intr_en & intr_status, ioaddr + XGMAC_DMA_CH_STATUS(chan));384 385	return ret;386}387 388static int dwxgmac2_get_hw_feature(void __iomem *ioaddr,389				   struct dma_features *dma_cap)390{391	u32 hw_cap;392 393	/* MAC HW feature 0 */394	hw_cap = readl(ioaddr + XGMAC_HW_FEATURE0);395	dma_cap->edma = (hw_cap & XGMAC_HWFEAT_EDMA) >> 31;396	dma_cap->ediffc = (hw_cap & XGMAC_HWFEAT_EDIFFC) >> 30;397	dma_cap->vxn = (hw_cap & XGMAC_HWFEAT_VXN) >> 29;398	dma_cap->vlins = (hw_cap & XGMAC_HWFEAT_SAVLANINS) >> 27;399	dma_cap->tssrc = (hw_cap & XGMAC_HWFEAT_TSSTSSEL) >> 25;400	dma_cap->multi_addr = (hw_cap & XGMAC_HWFEAT_ADDMACADRSEL) >> 18;401	dma_cap->rx_coe = (hw_cap & XGMAC_HWFEAT_RXCOESEL) >> 16;402	dma_cap->tx_coe = (hw_cap & XGMAC_HWFEAT_TXCOESEL) >> 14;403	dma_cap->eee = (hw_cap & XGMAC_HWFEAT_EEESEL) >> 13;404	dma_cap->atime_stamp = (hw_cap & XGMAC_HWFEAT_TSSEL) >> 12;405	dma_cap->av = (hw_cap & XGMAC_HWFEAT_AVSEL) >> 11;406	dma_cap->av &= !((hw_cap & XGMAC_HWFEAT_RAVSEL) >> 10);407	dma_cap->arpoffsel = (hw_cap & XGMAC_HWFEAT_ARPOFFSEL) >> 9;408	dma_cap->rmon = (hw_cap & XGMAC_HWFEAT_MMCSEL) >> 8;409	dma_cap->pmt_magic_frame = (hw_cap & XGMAC_HWFEAT_MGKSEL) >> 7;410	dma_cap->pmt_remote_wake_up = (hw_cap & XGMAC_HWFEAT_RWKSEL) >> 6;411	dma_cap->sma_mdio = (hw_cap & XGMAC_HWFEAT_SMASEL) >> 5;412	dma_cap->vlhash = (hw_cap & XGMAC_HWFEAT_VLHASH) >> 4;413	dma_cap->half_duplex = (hw_cap & XGMAC_HWFEAT_HDSEL) >> 3;414	dma_cap->mbps_1000 = (hw_cap & XGMAC_HWFEAT_GMIISEL) >> 1;415 416	/* MAC HW feature 1 */417	hw_cap = readl(ioaddr + XGMAC_HW_FEATURE1);418	dma_cap->l3l4fnum = (hw_cap & XGMAC_HWFEAT_L3L4FNUM) >> 27;419	/* If L3L4FNUM < 8, then the number of L3L4 filters supported by420	 * XGMAC is equal to L3L4FNUM. From L3L4FNUM >= 8 the number of421	 * L3L4 filters goes on like 8, 16, 32, ... Current maximum of422	 * L3L4FNUM = 10.423	 */424	if (dma_cap->l3l4fnum >= 8 && dma_cap->l3l4fnum <= 10)425		dma_cap->l3l4fnum = 8 << (dma_cap->l3l4fnum - 8);426	else if (dma_cap->l3l4fnum > 10)427		dma_cap->l3l4fnum = 32;428 429	dma_cap->hash_tb_sz = (hw_cap & XGMAC_HWFEAT_HASHTBLSZ) >> 24;430	dma_cap->numtc = ((hw_cap & XGMAC_HWFEAT_NUMTC) >> 21) + 1;431	dma_cap->rssen = (hw_cap & XGMAC_HWFEAT_RSSEN) >> 20;432	dma_cap->dbgmem = (hw_cap & XGMAC_HWFEAT_DBGMEMA) >> 19;433	dma_cap->tsoen = (hw_cap & XGMAC_HWFEAT_TSOEN) >> 18;434	dma_cap->sphen = (hw_cap & XGMAC_HWFEAT_SPHEN) >> 17;435	dma_cap->dcben = (hw_cap & XGMAC_HWFEAT_DCBEN) >> 16;436 437	dma_cap->addr64 = (hw_cap & XGMAC_HWFEAT_ADDR64) >> 14;438	switch (dma_cap->addr64) {439	case 0:440		dma_cap->addr64 = 32;441		break;442	case 1:443		dma_cap->addr64 = 40;444		break;445	case 2:446		dma_cap->addr64 = 48;447		break;448	default:449		dma_cap->addr64 = 32;450		break;451	}452 453	dma_cap->advthword = (hw_cap & XGMAC_HWFEAT_ADVTHWORD) >> 13;454	dma_cap->ptoen = (hw_cap & XGMAC_HWFEAT_PTOEN) >> 12;455	dma_cap->osten = (hw_cap & XGMAC_HWFEAT_OSTEN) >> 11;456	dma_cap->tx_fifo_size =457		128 << ((hw_cap & XGMAC_HWFEAT_TXFIFOSIZE) >> 6);458	dma_cap->pfcen = (hw_cap & XGMAC_HWFEAT_PFCEN) >> 5;459	dma_cap->rx_fifo_size =460		128 << ((hw_cap & XGMAC_HWFEAT_RXFIFOSIZE) >> 0);461 462	/* MAC HW feature 2 */463	hw_cap = readl(ioaddr + XGMAC_HW_FEATURE2);464	dma_cap->aux_snapshot_n = (hw_cap & XGMAC_HWFEAT_AUXSNAPNUM) >> 28;465	dma_cap->pps_out_num = (hw_cap & XGMAC_HWFEAT_PPSOUTNUM) >> 24;466	dma_cap->number_tx_channel =467		((hw_cap & XGMAC_HWFEAT_TXCHCNT) >> 18) + 1;468	dma_cap->number_rx_channel =469		((hw_cap & XGMAC_HWFEAT_RXCHCNT) >> 12) + 1;470	dma_cap->number_tx_queues =471		((hw_cap & XGMAC_HWFEAT_TXQCNT) >> 6) + 1;472	dma_cap->number_rx_queues =473		((hw_cap & XGMAC_HWFEAT_RXQCNT) >> 0) + 1;474 475	/* MAC HW feature 3 */476	hw_cap = readl(ioaddr + XGMAC_HW_FEATURE3);477	dma_cap->tbs_ch_num = ((hw_cap & XGMAC_HWFEAT_TBSCH) >> 28) + 1;478	dma_cap->tbssel = (hw_cap & XGMAC_HWFEAT_TBSSEL) >> 27;479	dma_cap->fpesel = (hw_cap & XGMAC_HWFEAT_FPESEL) >> 26;480	dma_cap->sgfsel = (hw_cap & XGMAC_HWFEAT_SGFSEL) >> 25;481	dma_cap->estwid = (hw_cap & XGMAC_HWFEAT_ESTWID) >> 23;482	dma_cap->estdep = (hw_cap & XGMAC_HWFEAT_ESTDEP) >> 20;483	dma_cap->estsel = (hw_cap & XGMAC_HWFEAT_ESTSEL) >> 19;484	dma_cap->ttsfd = (hw_cap & XGMAC_HWFEAT_TTSFD) >> 16;485	dma_cap->asp = (hw_cap & XGMAC_HWFEAT_ASP) >> 14;486	dma_cap->dvlan = (hw_cap & XGMAC_HWFEAT_DVLAN) >> 13;487	dma_cap->frpes = (hw_cap & XGMAC_HWFEAT_FRPES) >> 11;488	dma_cap->frpbs = (hw_cap & XGMAC_HWFEAT_FRPPB) >> 9;489	dma_cap->pou_ost_en = (hw_cap & XGMAC_HWFEAT_POUOST) >> 8;490	dma_cap->frppipe_num = ((hw_cap & XGMAC_HWFEAT_FRPPIPE) >> 5) + 1;491	dma_cap->cbtisel = (hw_cap & XGMAC_HWFEAT_CBTISEL) >> 4;492	dma_cap->frpsel = (hw_cap & XGMAC_HWFEAT_FRPSEL) >> 3;493	dma_cap->nrvf_num = (hw_cap & XGMAC_HWFEAT_NRVF) >> 0;494 495	/* MAC HW feature 4 */496	hw_cap = readl(ioaddr + XGMAC_HW_FEATURE4);497	dma_cap->asp |= (hw_cap & XGMAC_HWFEAT_EASP) >> 2;498	dma_cap->pcsel = (hw_cap & XGMAC_HWFEAT_PCSEL) >> 0;499 500	return 0;501}502 503static void dwxgmac2_rx_watchdog(struct stmmac_priv *priv, void __iomem *ioaddr,504				 u32 riwt, u32 queue)505{506	writel(riwt & XGMAC_RWT, ioaddr + XGMAC_DMA_CH_Rx_WATCHDOG(queue));507}508 509static void dwxgmac2_set_rx_ring_len(struct stmmac_priv *priv,510				     void __iomem *ioaddr, u32 len, u32 chan)511{512	writel(len, ioaddr + XGMAC_DMA_CH_RxDESC_RING_LEN(chan));513}514 515static void dwxgmac2_set_tx_ring_len(struct stmmac_priv *priv,516				     void __iomem *ioaddr, u32 len, u32 chan)517{518	writel(len, ioaddr + XGMAC_DMA_CH_TxDESC_RING_LEN(chan));519}520 521static void dwxgmac2_set_rx_tail_ptr(struct stmmac_priv *priv,522				     void __iomem *ioaddr, u32 ptr, u32 chan)523{524	writel(ptr, ioaddr + XGMAC_DMA_CH_RxDESC_TAIL_LPTR(chan));525}526 527static void dwxgmac2_set_tx_tail_ptr(struct stmmac_priv *priv,528				     void __iomem *ioaddr, u32 ptr, u32 chan)529{530	writel(ptr, ioaddr + XGMAC_DMA_CH_TxDESC_TAIL_LPTR(chan));531}532 533static void dwxgmac2_enable_tso(struct stmmac_priv *priv, void __iomem *ioaddr,534				bool en, u32 chan)535{536	u32 value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));537 538	if (en)539		value |= XGMAC_TSE;540	else541		value &= ~XGMAC_TSE;542 543	writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));544}545 546static void dwxgmac2_qmode(struct stmmac_priv *priv, void __iomem *ioaddr,547			   u32 channel, u8 qmode)548{549	u32 value = readl(ioaddr + XGMAC_MTL_TXQ_OPMODE(channel));550	u32 flow = readl(ioaddr + XGMAC_RX_FLOW_CTRL);551 552	value &= ~XGMAC_TXQEN;553	if (qmode != MTL_QUEUE_AVB) {554		value |= 0x2 << XGMAC_TXQEN_SHIFT;555		writel(0, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(channel));556	} else {557		value |= 0x1 << XGMAC_TXQEN_SHIFT;558		writel(flow & (~XGMAC_RFE), ioaddr + XGMAC_RX_FLOW_CTRL);559	}560 561	writel(value, ioaddr +  XGMAC_MTL_TXQ_OPMODE(channel));562}563 564static void dwxgmac2_set_bfsize(struct stmmac_priv *priv, void __iomem *ioaddr,565				int bfsize, u32 chan)566{567	u32 value;568 569	value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));570	value &= ~XGMAC_RBSZ;571	value |= bfsize << XGMAC_RBSZ_SHIFT;572	writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));573}574 575static void dwxgmac2_enable_sph(struct stmmac_priv *priv, void __iomem *ioaddr,576				bool en, u32 chan)577{578	u32 value = readl(ioaddr + XGMAC_RX_CONFIG);579 580	value &= ~XGMAC_CONFIG_HDSMS;581	value |= XGMAC_CONFIG_HDSMS_256; /* Segment max 256 bytes */582	writel(value, ioaddr + XGMAC_RX_CONFIG);583 584	value = readl(ioaddr + XGMAC_DMA_CH_CONTROL(chan));585	if (en)586		value |= XGMAC_SPH;587	else588		value &= ~XGMAC_SPH;589	writel(value, ioaddr + XGMAC_DMA_CH_CONTROL(chan));590}591 592static int dwxgmac2_enable_tbs(struct stmmac_priv *priv, void __iomem *ioaddr,593			       bool en, u32 chan)594{595	u32 value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));596 597	if (en)598		value |= XGMAC_EDSE;599	else600		value &= ~XGMAC_EDSE;601 602	writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan));603 604	value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)) & XGMAC_EDSE;605	if (en && !value)606		return -EIO;607 608	writel(XGMAC_DEF_FTOS, ioaddr + XGMAC_DMA_TBS_CTRL0);609	writel(XGMAC_DEF_FTOS, ioaddr + XGMAC_DMA_TBS_CTRL1);610	writel(XGMAC_DEF_FTOS, ioaddr + XGMAC_DMA_TBS_CTRL2);611	writel(XGMAC_DEF_FTOS, ioaddr + XGMAC_DMA_TBS_CTRL3);612	return 0;613}614 615const struct stmmac_dma_ops dwxgmac210_dma_ops = {616	.reset = dwxgmac2_dma_reset,617	.init = dwxgmac2_dma_init,618	.init_chan = dwxgmac2_dma_init_chan,619	.init_rx_chan = dwxgmac2_dma_init_rx_chan,620	.init_tx_chan = dwxgmac2_dma_init_tx_chan,621	.axi = dwxgmac2_dma_axi,622	.dump_regs = dwxgmac2_dma_dump_regs,623	.dma_rx_mode = dwxgmac2_dma_rx_mode,624	.dma_tx_mode = dwxgmac2_dma_tx_mode,625	.enable_dma_irq = dwxgmac2_enable_dma_irq,626	.disable_dma_irq = dwxgmac2_disable_dma_irq,627	.start_tx = dwxgmac2_dma_start_tx,628	.stop_tx = dwxgmac2_dma_stop_tx,629	.start_rx = dwxgmac2_dma_start_rx,630	.stop_rx = dwxgmac2_dma_stop_rx,631	.dma_interrupt = dwxgmac2_dma_interrupt,632	.get_hw_feature = dwxgmac2_get_hw_feature,633	.rx_watchdog = dwxgmac2_rx_watchdog,634	.set_rx_ring_len = dwxgmac2_set_rx_ring_len,635	.set_tx_ring_len = dwxgmac2_set_tx_ring_len,636	.set_rx_tail_ptr = dwxgmac2_set_rx_tail_ptr,637	.set_tx_tail_ptr = dwxgmac2_set_tx_tail_ptr,638	.enable_tso = dwxgmac2_enable_tso,639	.qmode = dwxgmac2_qmode,640	.set_bfsize = dwxgmac2_set_bfsize,641	.enable_sph = dwxgmac2_enable_sph,642	.enable_tbs = dwxgmac2_enable_tbs,643};644