14fa9c49fSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 27ac6653aSJeff Kirsher /******************************************************************************* 37ac6653aSJeff Kirsher This is the driver for the MAC 10/100 on-chip Ethernet controller 47ac6653aSJeff Kirsher currently tested on all the ST boards based on STb7109 and stx7200 SoCs. 57ac6653aSJeff Kirsher 67ac6653aSJeff Kirsher DWC Ether MAC 10/100 Universal version 4.0 has been used for developing 77ac6653aSJeff Kirsher this code. 87ac6653aSJeff Kirsher 97ac6653aSJeff Kirsher This contains the functions to handle the dma. 107ac6653aSJeff Kirsher 117ac6653aSJeff Kirsher Copyright (C) 2007-2009 STMicroelectronics Ltd 127ac6653aSJeff Kirsher 137ac6653aSJeff Kirsher 147ac6653aSJeff Kirsher Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> 157ac6653aSJeff Kirsher *******************************************************************************/ 167ac6653aSJeff Kirsher 177ac6653aSJeff Kirsher #include <asm/io.h> 187ac6653aSJeff Kirsher #include "dwmac100.h" 197ac6653aSJeff Kirsher #include "dwmac_dma.h" 207ac6653aSJeff Kirsher 2150ca903aSNiklas Cassel static void dwmac100_dma_init(void __iomem *ioaddr, 2224aaed0cSJose Abreu struct stmmac_dma_cfg *dma_cfg, int atds) 237ac6653aSJeff Kirsher { 247ac6653aSJeff Kirsher /* Enable Application Access by writing to DMA CSR0 */ 2550ca903aSNiklas Cassel writel(DMA_BUS_MODE_DEFAULT | (dma_cfg->pbl << DMA_BUS_MODE_PBL_SHIFT), 267ac6653aSJeff Kirsher ioaddr + DMA_BUS_MODE); 277ac6653aSJeff Kirsher 287ac6653aSJeff Kirsher /* Mask interrupts by writing to CSR7 */ 297ac6653aSJeff Kirsher writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA); 3024aaed0cSJose Abreu } 317ac6653aSJeff Kirsher 3224aaed0cSJose Abreu static void dwmac100_dma_init_rx(void __iomem *ioaddr, 3324aaed0cSJose Abreu struct stmmac_dma_cfg *dma_cfg, 3424aaed0cSJose Abreu u32 dma_rx_phy, u32 chan) 3524aaed0cSJose Abreu { 3624aaed0cSJose Abreu /* RX descriptor base addr lists must be written into DMA CSR3 */ 3724aaed0cSJose Abreu writel(dma_rx_phy, ioaddr + DMA_RCV_BASE_ADDR); 3824aaed0cSJose Abreu } 3924aaed0cSJose Abreu 4024aaed0cSJose Abreu static void dwmac100_dma_init_tx(void __iomem *ioaddr, 4124aaed0cSJose Abreu struct stmmac_dma_cfg *dma_cfg, 4224aaed0cSJose Abreu u32 dma_tx_phy, u32 chan) 4324aaed0cSJose Abreu { 4424aaed0cSJose Abreu /* TX descriptor base addr lists must be written into DMA CSR4 */ 4524aaed0cSJose Abreu writel(dma_tx_phy, ioaddr + DMA_TX_BASE_ADDR); 467ac6653aSJeff Kirsher } 477ac6653aSJeff Kirsher 48ceb69499SGiuseppe CAVALLARO /* Store and Forward capability is not used at all. 49ceb69499SGiuseppe CAVALLARO * 50ceb69499SGiuseppe CAVALLARO * The transmit threshold can be programmed by setting the TTC bits in the DMA 51ceb69499SGiuseppe CAVALLARO * control register. 52ceb69499SGiuseppe CAVALLARO */ 53ab0204e3SJose Abreu static void dwmac100_dma_operation_mode_tx(void __iomem *ioaddr, int mode, 54ab0204e3SJose Abreu u32 channel, int fifosz, u8 qmode) 557ac6653aSJeff Kirsher { 567ac6653aSJeff Kirsher u32 csr6 = readl(ioaddr + DMA_CONTROL); 577ac6653aSJeff Kirsher 58ab0204e3SJose Abreu if (mode <= 32) 597ac6653aSJeff Kirsher csr6 |= DMA_CONTROL_TTC_32; 60ab0204e3SJose Abreu else if (mode <= 64) 617ac6653aSJeff Kirsher csr6 |= DMA_CONTROL_TTC_64; 627ac6653aSJeff Kirsher else 637ac6653aSJeff Kirsher csr6 |= DMA_CONTROL_TTC_128; 647ac6653aSJeff Kirsher 657ac6653aSJeff Kirsher writel(csr6, ioaddr + DMA_CONTROL); 667ac6653aSJeff Kirsher } 677ac6653aSJeff Kirsher 68fbf68229SLABBE Corentin static void dwmac100_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space) 697ac6653aSJeff Kirsher { 707ac6653aSJeff Kirsher int i; 717ac6653aSJeff Kirsher 72f4458b92SThor Thayer for (i = 0; i < NUM_DWMAC100_DMA_REGS; i++) 73fbf68229SLABBE Corentin reg_space[DMA_BUS_MODE / 4 + i] = 74fbf68229SLABBE Corentin readl(ioaddr + DMA_BUS_MODE + i * 4); 7583d7af64SGiuseppe CAVALLARO 76fbf68229SLABBE Corentin reg_space[DMA_CUR_TX_BUF_ADDR / 4] = 77fbf68229SLABBE Corentin readl(ioaddr + DMA_CUR_TX_BUF_ADDR); 78fbf68229SLABBE Corentin reg_space[DMA_CUR_RX_BUF_ADDR / 4] = 79fbf68229SLABBE Corentin readl(ioaddr + DMA_CUR_RX_BUF_ADDR); 807ac6653aSJeff Kirsher } 817ac6653aSJeff Kirsher 82ceb69499SGiuseppe CAVALLARO /* DMA controller has two counters to track the number of the missed frames. */ 837ac6653aSJeff Kirsher static void dwmac100_dma_diagnostic_fr(void *data, struct stmmac_extra_stats *x, 847ac6653aSJeff Kirsher void __iomem *ioaddr) 857ac6653aSJeff Kirsher { 867ac6653aSJeff Kirsher struct net_device_stats *stats = (struct net_device_stats *)data; 877ac6653aSJeff Kirsher u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR); 887ac6653aSJeff Kirsher 897ac6653aSJeff Kirsher if (unlikely(csr8)) { 907ac6653aSJeff Kirsher if (csr8 & DMA_MISSED_FRAME_OVE) { 917ac6653aSJeff Kirsher stats->rx_over_errors += 0x800; 927ac6653aSJeff Kirsher x->rx_overflow_cntr += 0x800; 937ac6653aSJeff Kirsher } else { 947ac6653aSJeff Kirsher unsigned int ove_cntr; 957ac6653aSJeff Kirsher ove_cntr = ((csr8 & DMA_MISSED_FRAME_OVE_CNTR) >> 17); 967ac6653aSJeff Kirsher stats->rx_over_errors += ove_cntr; 977ac6653aSJeff Kirsher x->rx_overflow_cntr += ove_cntr; 987ac6653aSJeff Kirsher } 997ac6653aSJeff Kirsher 1007ac6653aSJeff Kirsher if (csr8 & DMA_MISSED_FRAME_OVE_M) { 1017ac6653aSJeff Kirsher stats->rx_missed_errors += 0xffff; 1027ac6653aSJeff Kirsher x->rx_missed_cntr += 0xffff; 1037ac6653aSJeff Kirsher } else { 1047ac6653aSJeff Kirsher unsigned int miss_f = (csr8 & DMA_MISSED_FRAME_M_CNTR); 1057ac6653aSJeff Kirsher stats->rx_missed_errors += miss_f; 1067ac6653aSJeff Kirsher x->rx_missed_cntr += miss_f; 1077ac6653aSJeff Kirsher } 1087ac6653aSJeff Kirsher } 1097ac6653aSJeff Kirsher } 1107ac6653aSJeff Kirsher 1117ac6653aSJeff Kirsher const struct stmmac_dma_ops dwmac100_dma_ops = { 112495db273SGiuseppe Cavallaro .reset = dwmac_dma_reset, 1137ac6653aSJeff Kirsher .init = dwmac100_dma_init, 11424aaed0cSJose Abreu .init_rx_chan = dwmac100_dma_init_rx, 11524aaed0cSJose Abreu .init_tx_chan = dwmac100_dma_init_tx, 1167ac6653aSJeff Kirsher .dump_regs = dwmac100_dump_dma_regs, 117ab0204e3SJose Abreu .dma_tx_mode = dwmac100_dma_operation_mode_tx, 1187ac6653aSJeff Kirsher .dma_diagnostic_fr = dwmac100_dma_diagnostic_fr, 1197ac6653aSJeff Kirsher .enable_dma_transmission = dwmac_enable_dma_transmission, 1207ac6653aSJeff Kirsher .enable_dma_irq = dwmac_enable_dma_irq, 1217ac6653aSJeff Kirsher .disable_dma_irq = dwmac_disable_dma_irq, 1227ac6653aSJeff Kirsher .start_tx = dwmac_dma_start_tx, 1237ac6653aSJeff Kirsher .stop_tx = dwmac_dma_stop_tx, 1247ac6653aSJeff Kirsher .start_rx = dwmac_dma_start_rx, 1257ac6653aSJeff Kirsher .stop_rx = dwmac_dma_stop_rx, 1267ac6653aSJeff Kirsher .dma_interrupt = dwmac_dma_interrupt, 1277ac6653aSJeff Kirsher }; 128