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