]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
net: smmac: allow configuring lower pbl values
[mirror_ubuntu-hirsute-kernel.git] / drivers / net / ethernet / stmicro / stmmac / dwmac1000_dma.c
CommitLineData
47dd7a54
GC
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
56b106ae 6 This contains the functions to handle the dma.
21d437cc 7
47dd7a54
GC
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
b7f080cf 29#include <asm/io.h>
21d437cc 30#include "dwmac1000.h"
aec7ff27 31#include "dwmac_dma.h"
47dd7a54 32
afea0365
GC
33static 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
6b3374cb 46 value &= ~DMA_AXI_WR_OSR_LMT;
afea0365
GC
47 value |= (axi->axi_wr_osr_lmt & DMA_AXI_WR_OSR_LMT_MASK) <<
48 DMA_AXI_WR_OSR_LMT_SHIFT;
49
6b3374cb 50 value &= ~DMA_AXI_RD_OSR_LMT;
afea0365
GC
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
50ca903a
NC
87static void dwmac1000_dma_init(void __iomem *ioaddr,
88 struct stmmac_dma_cfg *dma_cfg,
89 u32 dma_tx, u32 dma_rx, int atds)
47dd7a54 90{
afea0365 91 u32 value = readl(ioaddr + DMA_BUS_MODE);
89caaa2d
NC
92 int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
93 int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
47dd7a54 94
8327eb65 95 /*
afea0365
GC
96 * Set the DMA PBL (Programmable Burst Length) mode.
97 *
98 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
8327eb65 99 * post 3.5 mode bit acts as 8*PBL.
8327eb65 100 */
4022d039
NC
101 if (dma_cfg->pblx8)
102 value |= DMA_BUS_MODE_MAXPBL;
89caaa2d
NC
103 value |= DMA_BUS_MODE_USP;
104 value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
105 value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
106 value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
8327eb65
DS
107
108 /* Set the Fixed burst mode */
50ca903a 109 if (dma_cfg->fixed_burst)
8327eb65 110 value |= DMA_BUS_MODE_FB;
47dd7a54 111
b9cde0a8 112 /* Mixed Burst has no effect when fb is set */
50ca903a 113 if (dma_cfg->mixed_burst)
b9cde0a8
GC
114 value |= DMA_BUS_MODE_MB;
115
c24602ef
GC
116 if (atds)
117 value |= DMA_BUS_MODE_ATDS;
118
50ca903a 119 if (dma_cfg->aal)
afea0365 120 value |= DMA_BUS_MODE_AAL;
47dd7a54 121
afea0365 122 writel(value, ioaddr + DMA_BUS_MODE);
8327eb65 123
47dd7a54
GC
124 /* Mask interrupts by writing to CSR7 */
125 writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
126
ceb69499
GC
127 /* RX/TX descriptor base address lists must be written into
128 * DMA CSR3 and CSR4, respectively
129 */
47dd7a54
GC
130 writel(dma_tx, ioaddr + DMA_TX_BASE_ADDR);
131 writel(dma_rx, ioaddr + DMA_RCV_BASE_ADDR);
47dd7a54
GC
132}
133
f88203a2
VB
134static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
135{
136 csr6 &= ~DMA_CONTROL_RFA_MASK;
137 csr6 &= ~DMA_CONTROL_RFD_MASK;
138
139 /* Leave flow control disabled if receive fifo size is less than
140 * 4K or 0. Otherwise, send XOFF when fifo is 1K less than full,
141 * and send XON when 2K less than full.
142 */
143 if (rxfifosz < 4096) {
144 csr6 &= ~DMA_CONTROL_EFC;
145 pr_debug("GMAC: disabling flow control, rxfifo too small(%d)\n",
146 rxfifosz);
147 } else {
148 csr6 |= DMA_CONTROL_EFC;
149 csr6 |= RFA_FULL_MINUS_1K;
150 csr6 |= RFD_FULL_MINUS_2K;
151 }
152 return csr6;
153}
154
ad01b7d4 155static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode,
f88203a2 156 int rxmode, int rxfifosz)
47dd7a54
GC
157{
158 u32 csr6 = readl(ioaddr + DMA_CONTROL);
159
160 if (txmode == SF_DMA_MODE) {
83d7af64 161 pr_debug("GMAC: enable TX store and forward mode\n");
47dd7a54
GC
162 /* Transmit COE type 2 cannot be done in cut-through mode. */
163 csr6 |= DMA_CONTROL_TSF;
164 /* Operating on second frame increase the performance
ceb69499
GC
165 * especially when transmit store-and-forward is used.
166 */
47dd7a54
GC
167 csr6 |= DMA_CONTROL_OSF;
168 } else {
83d7af64 169 pr_debug("GMAC: disabling TX SF (threshold %d)\n", txmode);
47dd7a54
GC
170 csr6 &= ~DMA_CONTROL_TSF;
171 csr6 &= DMA_CONTROL_TC_TX_MASK;
af901ca1 172 /* Set the transmit threshold */
47dd7a54
GC
173 if (txmode <= 32)
174 csr6 |= DMA_CONTROL_TTC_32;
175 else if (txmode <= 64)
176 csr6 |= DMA_CONTROL_TTC_64;
177 else if (txmode <= 128)
178 csr6 |= DMA_CONTROL_TTC_128;
179 else if (txmode <= 192)
180 csr6 |= DMA_CONTROL_TTC_192;
181 else
182 csr6 |= DMA_CONTROL_TTC_256;
183 }
184
185 if (rxmode == SF_DMA_MODE) {
83d7af64 186 pr_debug("GMAC: enable RX store and forward mode\n");
47dd7a54
GC
187 csr6 |= DMA_CONTROL_RSF;
188 } else {
83d7af64 189 pr_debug("GMAC: disable RX SF mode (threshold %d)\n", rxmode);
47dd7a54
GC
190 csr6 &= ~DMA_CONTROL_RSF;
191 csr6 &= DMA_CONTROL_TC_RX_MASK;
192 if (rxmode <= 32)
193 csr6 |= DMA_CONTROL_RTC_32;
194 else if (rxmode <= 64)
195 csr6 |= DMA_CONTROL_RTC_64;
196 else if (rxmode <= 96)
197 csr6 |= DMA_CONTROL_RTC_96;
198 else
199 csr6 |= DMA_CONTROL_RTC_128;
200 }
201
f88203a2
VB
202 /* Configure flow control based on rx fifo size */
203 csr6 = dwmac1000_configure_fc(csr6, rxfifosz);
204
47dd7a54 205 writel(csr6, ioaddr + DMA_CONTROL);
47dd7a54
GC
206}
207
ad01b7d4 208static void dwmac1000_dump_dma_regs(void __iomem *ioaddr)
47dd7a54
GC
209{
210 int i;
211 pr_info(" DMA registers\n");
212 for (i = 0; i < 22; i++) {
213 if ((i < 9) || (i > 17)) {
214 int offset = i * 4;
215 pr_err("\t Reg No. %d (offset 0x%x): 0x%08x\n", i,
216 (DMA_BUS_MODE + offset),
217 readl(ioaddr + DMA_BUS_MODE + offset));
218 }
219 }
47dd7a54
GC
220}
221
f10a6a35
AT
222static void dwmac1000_get_hw_feature(void __iomem *ioaddr,
223 struct dma_features *dma_cap)
e7434821 224{
f10a6a35
AT
225 u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE);
226
227 dma_cap->mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
228 dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
229 dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
230 dma_cap->hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
231 dma_cap->multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5;
232 dma_cap->pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
233 dma_cap->sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
234 dma_cap->pmt_remote_wake_up = (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
235 dma_cap->pmt_magic_frame = (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
236 /* MMC */
237 dma_cap->rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
238 /* IEEE 1588-2002 */
239 dma_cap->time_stamp =
240 (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
241 /* IEEE 1588-2008 */
242 dma_cap->atime_stamp = (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
243 /* 802.3az - Energy-Efficient Ethernet (EEE) */
244 dma_cap->eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
245 dma_cap->av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
246 /* TX and RX csum */
247 dma_cap->tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16;
248 dma_cap->rx_coe_type1 = (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
249 dma_cap->rx_coe_type2 = (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
250 dma_cap->rxfifo_over_2048 = (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
251 /* TX and RX number of channels */
252 dma_cap->number_rx_channel = (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
253 dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
254 /* Alternate (enhanced) DESC mode */
255 dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
e7434821
GC
256}
257
62a2ab93
GC
258static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt)
259{
260 writel(riwt, ioaddr + DMA_RX_WATCHDOG);
261}
262
cadb7924 263const struct stmmac_dma_ops dwmac1000_dma_ops = {
495db273 264 .reset = dwmac_dma_reset,
21d437cc 265 .init = dwmac1000_dma_init,
afea0365 266 .axi = dwmac1000_dma_axi,
21d437cc
GC
267 .dump_regs = dwmac1000_dump_dma_regs,
268 .dma_mode = dwmac1000_dma_operation_mode,
aec7ff27
GC
269 .enable_dma_transmission = dwmac_enable_dma_transmission,
270 .enable_dma_irq = dwmac_enable_dma_irq,
271 .disable_dma_irq = dwmac_disable_dma_irq,
272 .start_tx = dwmac_dma_start_tx,
273 .stop_tx = dwmac_dma_stop_tx,
274 .start_rx = dwmac_dma_start_rx,
275 .stop_rx = dwmac_dma_stop_rx,
276 .dma_interrupt = dwmac_dma_interrupt,
e7434821 277 .get_hw_feature = dwmac1000_get_hw_feature,
62a2ab93 278 .rx_watchdog = dwmac1000_rx_watchdog,
db98a0b0 279};