LCOV - code coverage report
Current view: top level - drivers/net/ethernet/stmicro/stmmac - dwmac1000_dma.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 76 146 52.1 %
Date: 2022-04-01 14:35:51 Functions: 7 9 77.8 %
Branches: 11 54 20.4 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*******************************************************************************
       3                 :            :   This is the driver for the GMAC on-chip Ethernet controller for ST SoCs.
       4                 :            :   DWC Ether MAC 10/100/1000 Universal version 3.41a  has been used for
       5                 :            :   developing this code.
       6                 :            : 
       7                 :            :   This contains the functions to handle the dma.
       8                 :            : 
       9                 :            :   Copyright (C) 2007-2009  STMicroelectronics Ltd
      10                 :            : 
      11                 :            : 
      12                 :            :   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
      13                 :            : *******************************************************************************/
      14                 :            : 
      15                 :            : #include <asm/io.h>
      16                 :            : #include "dwmac1000.h"
      17                 :            : #include "dwmac_dma.h"
      18                 :            : 
      19                 :          0 : static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
      20                 :            : {
      21                 :          0 :         u32 value = readl(ioaddr + DMA_AXI_BUS_MODE);
      22                 :          0 :         int i;
      23                 :            : 
      24         [ #  # ]:          0 :         pr_info("dwmac1000: Master AXI performs %s burst length\n",
      25                 :            :                 !(value & DMA_AXI_UNDEF) ? "fixed" : "any");
      26                 :            : 
      27         [ #  # ]:          0 :         if (axi->axi_lpi_en)
      28                 :          0 :                 value |= DMA_AXI_EN_LPI;
      29         [ #  # ]:          0 :         if (axi->axi_xit_frm)
      30                 :          0 :                 value |= DMA_AXI_LPI_XIT_FRM;
      31                 :            : 
      32                 :          0 :         value &= ~DMA_AXI_WR_OSR_LMT;
      33                 :          0 :         value |= (axi->axi_wr_osr_lmt & DMA_AXI_WR_OSR_LMT_MASK) <<
      34                 :            :                  DMA_AXI_WR_OSR_LMT_SHIFT;
      35                 :            : 
      36                 :          0 :         value &= ~DMA_AXI_RD_OSR_LMT;
      37                 :          0 :         value |= (axi->axi_rd_osr_lmt & DMA_AXI_RD_OSR_LMT_MASK) <<
      38                 :            :                  DMA_AXI_RD_OSR_LMT_SHIFT;
      39                 :            : 
      40                 :            :         /* Depending on the UNDEF bit the Master AXI will perform any burst
      41                 :            :          * length according to the BLEN programmed (by default all BLEN are
      42                 :            :          * set).
      43                 :            :          */
      44         [ #  # ]:          0 :         for (i = 0; i < AXI_BLEN; i++) {
      45   [ #  #  #  #  :          0 :                 switch (axi->axi_blen[i]) {
             #  #  #  # ]
      46                 :          0 :                 case 256:
      47                 :          0 :                         value |= DMA_AXI_BLEN256;
      48                 :          0 :                         break;
      49                 :          0 :                 case 128:
      50                 :          0 :                         value |= DMA_AXI_BLEN128;
      51                 :          0 :                         break;
      52                 :          0 :                 case 64:
      53                 :          0 :                         value |= DMA_AXI_BLEN64;
      54                 :          0 :                         break;
      55                 :          0 :                 case 32:
      56                 :          0 :                         value |= DMA_AXI_BLEN32;
      57                 :          0 :                         break;
      58                 :          0 :                 case 16:
      59                 :          0 :                         value |= DMA_AXI_BLEN16;
      60                 :          0 :                         break;
      61                 :          0 :                 case 8:
      62                 :          0 :                         value |= DMA_AXI_BLEN8;
      63                 :          0 :                         break;
      64                 :          0 :                 case 4:
      65                 :          0 :                         value |= DMA_AXI_BLEN4;
      66                 :          0 :                         break;
      67                 :            :                 }
      68                 :          0 :         }
      69                 :            : 
      70                 :          0 :         writel(value, ioaddr + DMA_AXI_BUS_MODE);
      71                 :          0 : }
      72                 :            : 
      73                 :         21 : static void dwmac1000_dma_init(void __iomem *ioaddr,
      74                 :            :                                struct stmmac_dma_cfg *dma_cfg, int atds)
      75                 :            : {
      76                 :         21 :         u32 value = readl(ioaddr + DMA_BUS_MODE);
      77         [ +  - ]:         21 :         int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
      78         [ +  - ]:         21 :         int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
      79                 :            : 
      80                 :            :         /*
      81                 :            :          * Set the DMA PBL (Programmable Burst Length) mode.
      82                 :            :          *
      83                 :            :          * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
      84                 :            :          * post 3.5 mode bit acts as 8*PBL.
      85                 :            :          */
      86         [ +  - ]:         21 :         if (dma_cfg->pblx8)
      87                 :         21 :                 value |= DMA_BUS_MODE_MAXPBL;
      88                 :         21 :         value |= DMA_BUS_MODE_USP;
      89                 :         21 :         value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
      90                 :         21 :         value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
      91                 :         21 :         value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
      92                 :            : 
      93                 :            :         /* Set the Fixed burst mode */
      94         [ +  - ]:         21 :         if (dma_cfg->fixed_burst)
      95                 :         21 :                 value |= DMA_BUS_MODE_FB;
      96                 :            : 
      97                 :            :         /* Mixed Burst has no effect when fb is set */
      98         [ -  + ]:         21 :         if (dma_cfg->mixed_burst)
      99                 :          0 :                 value |= DMA_BUS_MODE_MB;
     100                 :            : 
     101         [ +  + ]:         21 :         if (atds)
     102                 :         13 :                 value |= DMA_BUS_MODE_ATDS;
     103                 :            : 
     104         [ -  + ]:         21 :         if (dma_cfg->aal)
     105                 :          0 :                 value |= DMA_BUS_MODE_AAL;
     106                 :            : 
     107                 :         21 :         writel(value, ioaddr + DMA_BUS_MODE);
     108                 :            : 
     109                 :            :         /* Mask interrupts by writing to CSR7 */
     110                 :         21 :         writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
     111                 :         21 : }
     112                 :            : 
     113                 :         21 : static void dwmac1000_dma_init_rx(void __iomem *ioaddr,
     114                 :            :                                   struct stmmac_dma_cfg *dma_cfg,
     115                 :            :                                   dma_addr_t dma_rx_phy, u32 chan)
     116                 :            : {
     117                 :            :         /* RX descriptor base address list must be written into DMA CSR3 */
     118                 :         21 :         writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
     119                 :         21 : }
     120                 :            : 
     121                 :         21 : static void dwmac1000_dma_init_tx(void __iomem *ioaddr,
     122                 :            :                                   struct stmmac_dma_cfg *dma_cfg,
     123                 :            :                                   dma_addr_t dma_tx_phy, u32 chan)
     124                 :            : {
     125                 :            :         /* TX descriptor base address list must be written into DMA CSR4 */
     126                 :         21 :         writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
     127                 :         21 : }
     128                 :            : 
     129                 :         21 : static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
     130                 :            : {
     131                 :         21 :         csr6 &= ~DMA_CONTROL_RFA_MASK;
     132                 :         21 :         csr6 &= ~DMA_CONTROL_RFD_MASK;
     133                 :            : 
     134                 :            :         /* Leave flow control disabled if receive fifo size is less than
     135                 :            :          * 4K or 0. Otherwise, send XOFF when fifo is 1K less than full,
     136                 :            :          * and send XON when 2K less than full.
     137                 :            :          */
     138                 :         21 :         if (rxfifosz < 4096) {
     139                 :         21 :                 csr6 &= ~DMA_CONTROL_EFC;
     140                 :         21 :                 pr_debug("GMAC: disabling flow control, rxfifo too small(%d)\n",
     141                 :            :                          rxfifosz);
     142                 :            :         } else {
     143                 :          0 :                 csr6 |= DMA_CONTROL_EFC;
     144                 :          0 :                 csr6 |= RFA_FULL_MINUS_1K;
     145                 :          0 :                 csr6 |= RFD_FULL_MINUS_2K;
     146                 :            :         }
     147                 :         21 :         return csr6;
     148                 :            : }
     149                 :            : 
     150                 :         21 : static void dwmac1000_dma_operation_mode_rx(void __iomem *ioaddr, int mode,
     151                 :            :                                             u32 channel, int fifosz, u8 qmode)
     152                 :            : {
     153                 :         21 :         u32 csr6 = readl(ioaddr + DMA_CONTROL);
     154                 :            : 
     155         [ +  - ]:         21 :         if (mode == SF_DMA_MODE) {
     156                 :         21 :                 pr_debug("GMAC: enable RX store and forward mode\n");
     157                 :         21 :                 csr6 |= DMA_CONTROL_RSF;
     158                 :            :         } else {
     159                 :          0 :                 pr_debug("GMAC: disable RX SF mode (threshold %d)\n", mode);
     160                 :          0 :                 csr6 &= ~DMA_CONTROL_RSF;
     161                 :          0 :                 csr6 &= DMA_CONTROL_TC_RX_MASK;
     162         [ #  # ]:          0 :                 if (mode <= 32)
     163                 :          0 :                         csr6 |= DMA_CONTROL_RTC_32;
     164         [ #  # ]:          0 :                 else if (mode <= 64)
     165                 :            :                         csr6 |= DMA_CONTROL_RTC_64;
     166         [ #  # ]:          0 :                 else if (mode <= 96)
     167                 :          0 :                         csr6 |= DMA_CONTROL_RTC_96;
     168                 :            :                 else
     169                 :          0 :                         csr6 |= DMA_CONTROL_RTC_128;
     170                 :            :         }
     171                 :            : 
     172                 :            :         /* Configure flow control based on rx fifo size */
     173         [ +  - ]:         21 :         csr6 = dwmac1000_configure_fc(csr6, fifosz);
     174                 :            : 
     175                 :         21 :         writel(csr6, ioaddr + DMA_CONTROL);
     176                 :         21 : }
     177                 :            : 
     178                 :         21 : static void dwmac1000_dma_operation_mode_tx(void __iomem *ioaddr, int mode,
     179                 :            :                                             u32 channel, int fifosz, u8 qmode)
     180                 :            : {
     181                 :         21 :         u32 csr6 = readl(ioaddr + DMA_CONTROL);
     182                 :            : 
     183         [ +  - ]:         21 :         if (mode == SF_DMA_MODE) {
     184                 :         21 :                 pr_debug("GMAC: enable TX store and forward mode\n");
     185                 :            :                 /* Transmit COE type 2 cannot be done in cut-through mode. */
     186                 :         21 :                 csr6 |= DMA_CONTROL_TSF;
     187                 :            :                 /* Operating on second frame increase the performance
     188                 :            :                  * especially when transmit store-and-forward is used.
     189                 :            :                  */
     190                 :         21 :                 csr6 |= DMA_CONTROL_OSF;
     191                 :            :         } else {
     192                 :          0 :                 pr_debug("GMAC: disabling TX SF (threshold %d)\n", mode);
     193                 :          0 :                 csr6 &= ~DMA_CONTROL_TSF;
     194                 :          0 :                 csr6 &= DMA_CONTROL_TC_TX_MASK;
     195                 :            :                 /* Set the transmit threshold */
     196         [ #  # ]:          0 :                 if (mode <= 32)
     197                 :          0 :                         csr6 |= DMA_CONTROL_TTC_32;
     198         [ #  # ]:          0 :                 else if (mode <= 64)
     199                 :            :                         csr6 |= DMA_CONTROL_TTC_64;
     200         [ #  # ]:          0 :                 else if (mode <= 128)
     201                 :          0 :                         csr6 |= DMA_CONTROL_TTC_128;
     202         [ #  # ]:          0 :                 else if (mode <= 192)
     203                 :          0 :                         csr6 |= DMA_CONTROL_TTC_192;
     204                 :            :                 else
     205                 :          0 :                         csr6 |= DMA_CONTROL_TTC_256;
     206                 :            :         }
     207                 :            : 
     208                 :         21 :         writel(csr6, ioaddr + DMA_CONTROL);
     209                 :         21 : }
     210                 :            : 
     211                 :          0 : static void dwmac1000_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space)
     212                 :            : {
     213                 :          0 :         int i;
     214                 :            : 
     215         [ #  # ]:          0 :         for (i = 0; i < NUM_DWMAC1000_DMA_REGS; i++)
     216         [ #  # ]:          0 :                 if ((i < 12) || (i > 17))
     217                 :          0 :                         reg_space[DMA_BUS_MODE / 4 + i] =
     218                 :          0 :                                 readl(ioaddr + DMA_BUS_MODE + i * 4);
     219                 :          0 : }
     220                 :            : 
     221                 :         21 : static void dwmac1000_get_hw_feature(void __iomem *ioaddr,
     222                 :            :                                      struct dma_features *dma_cap)
     223                 :            : {
     224                 :         21 :         u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE);
     225                 :            : 
     226                 :         21 :         dma_cap->mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
     227                 :         21 :         dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
     228                 :         21 :         dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
     229                 :         21 :         dma_cap->hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
     230                 :         21 :         dma_cap->multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5;
     231                 :         21 :         dma_cap->pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
     232                 :         21 :         dma_cap->sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
     233                 :         21 :         dma_cap->pmt_remote_wake_up = (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
     234                 :         21 :         dma_cap->pmt_magic_frame = (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
     235                 :            :         /* MMC */
     236                 :         21 :         dma_cap->rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
     237                 :            :         /* IEEE 1588-2002 */
     238                 :         21 :         dma_cap->time_stamp =
     239                 :         21 :             (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
     240                 :            :         /* IEEE 1588-2008 */
     241                 :         21 :         dma_cap->atime_stamp = (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
     242                 :            :         /* 802.3az - Energy-Efficient Ethernet (EEE) */
     243                 :         21 :         dma_cap->eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
     244                 :         21 :         dma_cap->av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
     245                 :            :         /* TX and RX csum */
     246                 :         21 :         dma_cap->tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16;
     247                 :         21 :         dma_cap->rx_coe_type1 = (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
     248                 :         21 :         dma_cap->rx_coe_type2 = (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
     249                 :         21 :         dma_cap->rxfifo_over_2048 = (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
     250                 :            :         /* TX and RX number of channels */
     251                 :         21 :         dma_cap->number_rx_channel = (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
     252                 :         21 :         dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
     253                 :            :         /* Alternate (enhanced) DESC mode */
     254                 :         21 :         dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
     255                 :         21 : }
     256                 :            : 
     257                 :         16 : static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt,
     258                 :            :                                   u32 number_chan)
     259                 :            : {
     260                 :         16 :         writel(riwt, ioaddr + DMA_RX_WATCHDOG);
     261                 :         16 : }
     262                 :            : 
     263                 :            : const struct stmmac_dma_ops dwmac1000_dma_ops = {
     264                 :            :         .reset = dwmac_dma_reset,
     265                 :            :         .init = dwmac1000_dma_init,
     266                 :            :         .init_rx_chan = dwmac1000_dma_init_rx,
     267                 :            :         .init_tx_chan = dwmac1000_dma_init_tx,
     268                 :            :         .axi = dwmac1000_dma_axi,
     269                 :            :         .dump_regs = dwmac1000_dump_dma_regs,
     270                 :            :         .dma_rx_mode = dwmac1000_dma_operation_mode_rx,
     271                 :            :         .dma_tx_mode = dwmac1000_dma_operation_mode_tx,
     272                 :            :         .enable_dma_transmission = dwmac_enable_dma_transmission,
     273                 :            :         .enable_dma_irq = dwmac_enable_dma_irq,
     274                 :            :         .disable_dma_irq = dwmac_disable_dma_irq,
     275                 :            :         .start_tx = dwmac_dma_start_tx,
     276                 :            :         .stop_tx = dwmac_dma_stop_tx,
     277                 :            :         .start_rx = dwmac_dma_start_rx,
     278                 :            :         .stop_rx = dwmac_dma_stop_rx,
     279                 :            :         .dma_interrupt = dwmac_dma_interrupt,
     280                 :            :         .get_hw_feature = dwmac1000_get_hw_feature,
     281                 :            :         .rx_watchdog = dwmac1000_rx_watchdog,
     282                 :            : };

Generated by: LCOV version 1.14