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