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