Linux-libre 5.0.14-gnu
[librecmc/linux-libre.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   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
29 static 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
83 static void dwmac1000_dma_init(void __iomem *ioaddr,
84                                struct stmmac_dma_cfg *dma_cfg, int atds)
85 {
86         u32 value = readl(ioaddr + DMA_BUS_MODE);
87         int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
88         int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
89
90         /*
91          * Set the DMA PBL (Programmable Burst Length) mode.
92          *
93          * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
94          * post 3.5 mode bit acts as 8*PBL.
95          */
96         if (dma_cfg->pblx8)
97                 value |= DMA_BUS_MODE_MAXPBL;
98         value |= DMA_BUS_MODE_USP;
99         value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
100         value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
101         value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
102
103         /* Set the Fixed burst mode */
104         if (dma_cfg->fixed_burst)
105                 value |= DMA_BUS_MODE_FB;
106
107         /* Mixed Burst has no effect when fb is set */
108         if (dma_cfg->mixed_burst)
109                 value |= DMA_BUS_MODE_MB;
110
111         if (atds)
112                 value |= DMA_BUS_MODE_ATDS;
113
114         if (dma_cfg->aal)
115                 value |= DMA_BUS_MODE_AAL;
116
117         writel(value, ioaddr + DMA_BUS_MODE);
118
119         /* Mask interrupts by writing to CSR7 */
120         writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
121 }
122
123 static void dwmac1000_dma_init_rx(void __iomem *ioaddr,
124                                   struct stmmac_dma_cfg *dma_cfg,
125                                   u32 dma_rx_phy, u32 chan)
126 {
127         /* RX descriptor base address list must be written into DMA CSR3 */
128         writel(dma_rx_phy, ioaddr + DMA_RCV_BASE_ADDR);
129 }
130
131 static void dwmac1000_dma_init_tx(void __iomem *ioaddr,
132                                   struct stmmac_dma_cfg *dma_cfg,
133                                   u32 dma_tx_phy, u32 chan)
134 {
135         /* TX descriptor base address list must be written into DMA CSR4 */
136         writel(dma_tx_phy, ioaddr + DMA_TX_BASE_ADDR);
137 }
138
139 static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
140 {
141         csr6 &= ~DMA_CONTROL_RFA_MASK;
142         csr6 &= ~DMA_CONTROL_RFD_MASK;
143
144         /* Leave flow control disabled if receive fifo size is less than
145          * 4K or 0. Otherwise, send XOFF when fifo is 1K less than full,
146          * and send XON when 2K less than full.
147          */
148         if (rxfifosz < 4096) {
149                 csr6 &= ~DMA_CONTROL_EFC;
150                 pr_debug("GMAC: disabling flow control, rxfifo too small(%d)\n",
151                          rxfifosz);
152         } else {
153                 csr6 |= DMA_CONTROL_EFC;
154                 csr6 |= RFA_FULL_MINUS_1K;
155                 csr6 |= RFD_FULL_MINUS_2K;
156         }
157         return csr6;
158 }
159
160 static void dwmac1000_dma_operation_mode_rx(void __iomem *ioaddr, int mode,
161                                             u32 channel, int fifosz, u8 qmode)
162 {
163         u32 csr6 = readl(ioaddr + DMA_CONTROL);
164
165         if (mode == SF_DMA_MODE) {
166                 pr_debug("GMAC: enable RX store and forward mode\n");
167                 csr6 |= DMA_CONTROL_RSF;
168         } else {
169                 pr_debug("GMAC: disable RX SF mode (threshold %d)\n", mode);
170                 csr6 &= ~DMA_CONTROL_RSF;
171                 csr6 &= DMA_CONTROL_TC_RX_MASK;
172                 if (mode <= 32)
173                         csr6 |= DMA_CONTROL_RTC_32;
174                 else if (mode <= 64)
175                         csr6 |= DMA_CONTROL_RTC_64;
176                 else if (mode <= 96)
177                         csr6 |= DMA_CONTROL_RTC_96;
178                 else
179                         csr6 |= DMA_CONTROL_RTC_128;
180         }
181
182         /* Configure flow control based on rx fifo size */
183         csr6 = dwmac1000_configure_fc(csr6, fifosz);
184
185         writel(csr6, ioaddr + DMA_CONTROL);
186 }
187
188 static void dwmac1000_dma_operation_mode_tx(void __iomem *ioaddr, int mode,
189                                             u32 channel, int fifosz, u8 qmode)
190 {
191         u32 csr6 = readl(ioaddr + DMA_CONTROL);
192
193         if (mode == SF_DMA_MODE) {
194                 pr_debug("GMAC: enable TX store and forward mode\n");
195                 /* Transmit COE type 2 cannot be done in cut-through mode. */
196                 csr6 |= DMA_CONTROL_TSF;
197                 /* Operating on second frame increase the performance
198                  * especially when transmit store-and-forward is used.
199                  */
200                 csr6 |= DMA_CONTROL_OSF;
201         } else {
202                 pr_debug("GMAC: disabling TX SF (threshold %d)\n", mode);
203                 csr6 &= ~DMA_CONTROL_TSF;
204                 csr6 &= DMA_CONTROL_TC_TX_MASK;
205                 /* Set the transmit threshold */
206                 if (mode <= 32)
207                         csr6 |= DMA_CONTROL_TTC_32;
208                 else if (mode <= 64)
209                         csr6 |= DMA_CONTROL_TTC_64;
210                 else if (mode <= 128)
211                         csr6 |= DMA_CONTROL_TTC_128;
212                 else if (mode <= 192)
213                         csr6 |= DMA_CONTROL_TTC_192;
214                 else
215                         csr6 |= DMA_CONTROL_TTC_256;
216         }
217
218         writel(csr6, ioaddr + DMA_CONTROL);
219 }
220
221 static void dwmac1000_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space)
222 {
223         int i;
224
225         for (i = 0; i < NUM_DWMAC1000_DMA_REGS; i++)
226                 if ((i < 12) || (i > 17))
227                         reg_space[DMA_BUS_MODE / 4 + i] =
228                                 readl(ioaddr + DMA_BUS_MODE + i * 4);
229 }
230
231 static void dwmac1000_get_hw_feature(void __iomem *ioaddr,
232                                      struct dma_features *dma_cap)
233 {
234         u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE);
235
236         dma_cap->mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
237         dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
238         dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
239         dma_cap->hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
240         dma_cap->multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5;
241         dma_cap->pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
242         dma_cap->sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
243         dma_cap->pmt_remote_wake_up = (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
244         dma_cap->pmt_magic_frame = (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
245         /* MMC */
246         dma_cap->rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
247         /* IEEE 1588-2002 */
248         dma_cap->time_stamp =
249             (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
250         /* IEEE 1588-2008 */
251         dma_cap->atime_stamp = (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
252         /* 802.3az - Energy-Efficient Ethernet (EEE) */
253         dma_cap->eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
254         dma_cap->av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
255         /* TX and RX csum */
256         dma_cap->tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16;
257         dma_cap->rx_coe_type1 = (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
258         dma_cap->rx_coe_type2 = (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
259         dma_cap->rxfifo_over_2048 = (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
260         /* TX and RX number of channels */
261         dma_cap->number_rx_channel = (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
262         dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
263         /* Alternate (enhanced) DESC mode */
264         dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
265 }
266
267 static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt,
268                                   u32 number_chan)
269 {
270         writel(riwt, ioaddr + DMA_RX_WATCHDOG);
271 }
272
273 const struct stmmac_dma_ops dwmac1000_dma_ops = {
274         .reset = dwmac_dma_reset,
275         .init = dwmac1000_dma_init,
276         .init_rx_chan = dwmac1000_dma_init_rx,
277         .init_tx_chan = dwmac1000_dma_init_tx,
278         .axi = dwmac1000_dma_axi,
279         .dump_regs = dwmac1000_dump_dma_regs,
280         .dma_rx_mode = dwmac1000_dma_operation_mode_rx,
281         .dma_tx_mode = dwmac1000_dma_operation_mode_tx,
282         .enable_dma_transmission = dwmac_enable_dma_transmission,
283         .enable_dma_irq = dwmac_enable_dma_irq,
284         .disable_dma_irq = dwmac_disable_dma_irq,
285         .start_tx = dwmac_dma_start_tx,
286         .stop_tx = dwmac_dma_stop_tx,
287         .start_rx = dwmac_dma_start_rx,
288         .stop_rx = dwmac_dma_stop_rx,
289         .dma_interrupt = dwmac_dma_interrupt,
290         .get_hw_feature = dwmac1000_get_hw_feature,
291         .rx_watchdog = dwmac1000_rx_watchdog,
292 };