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
33static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb,
34			      int burst_len, u32 dma_tx, u32 dma_rx, int atds)
35{
36	u32 value = readl(ioaddr + DMA_BUS_MODE);
37	int limit;
38
39	/* DMA SW reset */
40	value |= DMA_BUS_MODE_SFT_RESET;
41	writel(value, ioaddr + DMA_BUS_MODE);
42	limit = 10;
43	while (limit--) {
44		if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET))
45			break;
46		mdelay(10);
47	}
48	if (limit < 0)
49		return -EBUSY;
50
51	/*
52	 * Set the DMA PBL (Programmable Burst Length) mode
53	 * Before stmmac core 3.50 this mode bit was 4xPBL, and
54	 * post 3.5 mode bit acts as 8*PBL.
55	 * For core rev < 3.5, when the core is set for 4xPBL mode, the
56	 * DMA transfers the data in 4, 8, 16, 32, 64 & 128 beats
57	 * depending on pbl value.
58	 * For core rev > 3.5, when the core is set for 8xPBL mode, the
59	 * DMA transfers the data in 8, 16, 32, 64, 128 & 256 beats
60	 * depending on pbl value.
61	 */
62	value = DMA_BUS_MODE_PBL | ((pbl << DMA_BUS_MODE_PBL_SHIFT) |
63				    (pbl << DMA_BUS_MODE_RPBL_SHIFT));
64
65	/* Set the Fixed burst mode */
66	if (fb)
67		value |= DMA_BUS_MODE_FB;
68
69	/* Mixed Burst has no effect when fb is set */
70	if (mb)
71		value |= DMA_BUS_MODE_MB;
72
73	if (atds)
74		value |= DMA_BUS_MODE_ATDS;
75
76	writel(value, ioaddr + DMA_BUS_MODE);
77
78	/* In case of GMAC AXI configuration, program the DMA_AXI_BUS_MODE
79	 * for supported bursts.
80	 *
81	 * Note: This is applicable only for revision GMACv3.61a. For
82	 * older version this register is reserved and shall have no
83	 * effect.
84	 *
85	 * Note:
86	 *  For Fixed Burst Mode: if we directly write 0xFF to this
87	 *  register using the configurations pass from platform code,
88	 *  this would ensure that all bursts supported by core are set
89	 *  and those which are not supported would remain ineffective.
90	 *
91	 *  For Non Fixed Burst Mode: provide the maximum value of the
92	 *  burst length. Any burst equal or below the provided burst
93	 *  length would be allowed to perform.
94	 */
95	writel(burst_len, ioaddr + DMA_AXI_BUS_MODE);
96
97	/* Mask interrupts by writing to CSR7 */
98	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
99
100	/* RX/TX descriptor base address lists must be written into
101	 * DMA CSR3 and CSR4, respectively
102	 */
103	writel(dma_tx, ioaddr + DMA_TX_BASE_ADDR);
104	writel(dma_rx, ioaddr + DMA_RCV_BASE_ADDR);
105
106	return 0;
107}
108
109static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
110{
111	csr6 &= ~DMA_CONTROL_RFA_MASK;
112	csr6 &= ~DMA_CONTROL_RFD_MASK;
113
114	/* Leave flow control disabled if receive fifo size is less than
115	 * 4K or 0. Otherwise, send XOFF when fifo is 1K less than full,
116	 * and send XON when 2K less than full.
117	 */
118	if (rxfifosz < 4096) {
119		csr6 &= ~DMA_CONTROL_EFC;
120		pr_debug("GMAC: disabling flow control, rxfifo too small(%d)\n",
121			 rxfifosz);
122	} else {
123		csr6 |= DMA_CONTROL_EFC;
124		csr6 |= RFA_FULL_MINUS_1K;
125		csr6 |= RFD_FULL_MINUS_2K;
126	}
127	return csr6;
128}
129
130static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode,
131					 int rxmode, int rxfifosz)
132{
133	u32 csr6 = readl(ioaddr + DMA_CONTROL);
134
135	if (txmode == SF_DMA_MODE) {
136		pr_debug("GMAC: enable TX store and forward mode\n");
137		/* Transmit COE type 2 cannot be done in cut-through mode. */
138		csr6 |= DMA_CONTROL_TSF;
139		/* Operating on second frame increase the performance
140		 * especially when transmit store-and-forward is used.
141		 */
142		csr6 |= DMA_CONTROL_OSF;
143	} else {
144		pr_debug("GMAC: disabling TX SF (threshold %d)\n", txmode);
145		csr6 &= ~DMA_CONTROL_TSF;
146		csr6 &= DMA_CONTROL_TC_TX_MASK;
147		/* Set the transmit threshold */
148		if (txmode <= 32)
149			csr6 |= DMA_CONTROL_TTC_32;
150		else if (txmode <= 64)
151			csr6 |= DMA_CONTROL_TTC_64;
152		else if (txmode <= 128)
153			csr6 |= DMA_CONTROL_TTC_128;
154		else if (txmode <= 192)
155			csr6 |= DMA_CONTROL_TTC_192;
156		else
157			csr6 |= DMA_CONTROL_TTC_256;
158	}
159
160	if (rxmode == SF_DMA_MODE) {
161		pr_debug("GMAC: enable RX store and forward mode\n");
162		csr6 |= DMA_CONTROL_RSF;
163	} else {
164		pr_debug("GMAC: disable RX SF mode (threshold %d)\n", rxmode);
165		csr6 &= ~DMA_CONTROL_RSF;
166		csr6 &= DMA_CONTROL_TC_RX_MASK;
167		if (rxmode <= 32)
168			csr6 |= DMA_CONTROL_RTC_32;
169		else if (rxmode <= 64)
170			csr6 |= DMA_CONTROL_RTC_64;
171		else if (rxmode <= 96)
172			csr6 |= DMA_CONTROL_RTC_96;
173		else
174			csr6 |= DMA_CONTROL_RTC_128;
175	}
176
177	/* Configure flow control based on rx fifo size */
178	csr6 = dwmac1000_configure_fc(csr6, rxfifosz);
179
180	writel(csr6, ioaddr + DMA_CONTROL);
181}
182
183static void dwmac1000_dump_dma_regs(void __iomem *ioaddr)
184{
185	int i;
186	pr_info(" DMA registers\n");
187	for (i = 0; i < 22; i++) {
188		if ((i < 9) || (i > 17)) {
189			int offset = i * 4;
190			pr_err("\t Reg No. %d (offset 0x%x): 0x%08x\n", i,
191			       (DMA_BUS_MODE + offset),
192			       readl(ioaddr + DMA_BUS_MODE + offset));
193		}
194	}
195}
196
197static unsigned int dwmac1000_get_hw_feature(void __iomem *ioaddr)
198{
199	return readl(ioaddr + DMA_HW_FEATURE);
200}
201
202static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt)
203{
204	writel(riwt, ioaddr + DMA_RX_WATCHDOG);
205}
206
207const struct stmmac_dma_ops dwmac1000_dma_ops = {
208	.init = dwmac1000_dma_init,
209	.dump_regs = dwmac1000_dump_dma_regs,
210	.dma_mode = dwmac1000_dma_operation_mode,
211	.enable_dma_transmission = dwmac_enable_dma_transmission,
212	.enable_dma_irq = dwmac_enable_dma_irq,
213	.disable_dma_irq = dwmac_disable_dma_irq,
214	.start_tx = dwmac_dma_start_tx,
215	.stop_tx = dwmac_dma_stop_tx,
216	.start_rx = dwmac_dma_start_rx,
217	.stop_rx = dwmac_dma_stop_rx,
218	.dma_interrupt = dwmac_dma_interrupt,
219	.get_hw_feature = dwmac1000_get_hw_feature,
220	.rx_watchdog = dwmac1000_rx_watchdog,
221};
222