aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/stmmac/dwmac_lib.c
diff options
context:
space:
mode:
authorGiuseppe CAVALLARO <peppe.cavallaro@st.com>2010-01-06 18:07:18 -0500
committerDavid S. Miller <davem@davemloft.net>2010-01-07 20:06:09 -0500
commitaec7ff278145280c2c78377aeb98feed02c8b636 (patch)
treefa03f8eac900b08e278b64ad76d825400907af9c /drivers/net/stmmac/dwmac_lib.c
parentdb98a0b001df79ffcdd4f231c3516411786a1113 (diff)
stmmac: move the dma out from the main
This patch moves the dma related functions (interrupt, start, stop etc.) out from the main driver code. This will help to support new DMA engines. Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/stmmac/dwmac_lib.c')
-rw-r--r--drivers/net/stmmac/dwmac_lib.c263
1 files changed, 263 insertions, 0 deletions
diff --git a/drivers/net/stmmac/dwmac_lib.c b/drivers/net/stmmac/dwmac_lib.c
new file mode 100644
index 000000000000..d4adb1eaa447
--- /dev/null
+++ b/drivers/net/stmmac/dwmac_lib.c
@@ -0,0 +1,263 @@
1/*******************************************************************************
2 Copyright (C) 2007-2009 STMicroelectronics Ltd
3
4 This program is free software; you can redistribute it and/or modify it
5 under the terms and conditions of the GNU General Public License,
6 version 2, as published by the Free Software Foundation.
7
8 This program is distributed in the hope it will be useful, but WITHOUT
9 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 more details.
12
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16
17 The full GNU General Public License is included in this distribution in
18 the file called "COPYING".
19
20 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
21*******************************************************************************/
22
23#include <linux/io.h>
24#include "common.h"
25#include "dwmac_dma.h"
26
27#undef DWMAC_DMA_DEBUG
28#ifdef DWMAC_DMA_DEBUG
29#define DBG(fmt, args...) printk(fmt, ## args)
30#else
31#define DBG(fmt, args...) do { } while (0)
32#endif
33
34/* CSR1 enables the transmit DMA to check for new descriptor */
35void dwmac_enable_dma_transmission(unsigned long ioaddr)
36{
37 writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
38}
39
40void dwmac_enable_dma_irq(unsigned long ioaddr)
41{
42 writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
43}
44
45void dwmac_disable_dma_irq(unsigned long ioaddr)
46{
47 writel(0, ioaddr + DMA_INTR_ENA);
48}
49
50void dwmac_dma_start_tx(unsigned long ioaddr)
51{
52 u32 value = readl(ioaddr + DMA_CONTROL);
53 value |= DMA_CONTROL_ST;
54 writel(value, ioaddr + DMA_CONTROL);
55 return;
56}
57
58void dwmac_dma_stop_tx(unsigned long ioaddr)
59{
60 u32 value = readl(ioaddr + DMA_CONTROL);
61 value &= ~DMA_CONTROL_ST;
62 writel(value, ioaddr + DMA_CONTROL);
63 return;
64}
65
66void dwmac_dma_start_rx(unsigned long ioaddr)
67{
68 u32 value = readl(ioaddr + DMA_CONTROL);
69 value |= DMA_CONTROL_SR;
70 writel(value, ioaddr + DMA_CONTROL);
71
72 return;
73}
74
75void dwmac_dma_stop_rx(unsigned long ioaddr)
76{
77 u32 value = readl(ioaddr + DMA_CONTROL);
78 value &= ~DMA_CONTROL_SR;
79 writel(value, ioaddr + DMA_CONTROL);
80
81 return;
82}
83
84#ifdef DWMAC_DMA_DEBUG
85static void show_tx_process_state(unsigned int status)
86{
87 unsigned int state;
88 state = (status & DMA_STATUS_TS_MASK) >> DMA_STATUS_TS_SHIFT;
89
90 switch (state) {
91 case 0:
92 pr_info("- TX (Stopped): Reset or Stop command\n");
93 break;
94 case 1:
95 pr_info("- TX (Running):Fetching the Tx desc\n");
96 break;
97 case 2:
98 pr_info("- TX (Running): Waiting for end of tx\n");
99 break;
100 case 3:
101 pr_info("- TX (Running): Reading the data "
102 "and queuing the data into the Tx buf\n");
103 break;
104 case 6:
105 pr_info("- TX (Suspended): Tx Buff Underflow "
106 "or an unavailable Transmit descriptor\n");
107 break;
108 case 7:
109 pr_info("- TX (Running): Closing Tx descriptor\n");
110 break;
111 default:
112 break;
113 }
114 return;
115}
116
117static void show_rx_process_state(unsigned int status)
118{
119 unsigned int state;
120 state = (status & DMA_STATUS_RS_MASK) >> DMA_STATUS_RS_SHIFT;
121
122 switch (state) {
123 case 0:
124 pr_info("- RX (Stopped): Reset or Stop command\n");
125 break;
126 case 1:
127 pr_info("- RX (Running): Fetching the Rx desc\n");
128 break;
129 case 2:
130 pr_info("- RX (Running):Checking for end of pkt\n");
131 break;
132 case 3:
133 pr_info("- RX (Running): Waiting for Rx pkt\n");
134 break;
135 case 4:
136 pr_info("- RX (Suspended): Unavailable Rx buf\n");
137 break;
138 case 5:
139 pr_info("- RX (Running): Closing Rx descriptor\n");
140 break;
141 case 6:
142 pr_info("- RX(Running): Flushing the current frame"
143 " from the Rx buf\n");
144 break;
145 case 7:
146 pr_info("- RX (Running): Queuing the Rx frame"
147 " from the Rx buf into memory\n");
148 break;
149 default:
150 break;
151 }
152 return;
153}
154#endif
155
156int dwmac_dma_interrupt(unsigned long ioaddr,
157 struct stmmac_extra_stats *x)
158{
159 int ret = 0;
160 /* read the status register (CSR5) */
161 u32 intr_status = readl(ioaddr + DMA_STATUS);
162
163 DBG(INFO, "%s: [CSR5: 0x%08x]\n", __func__, intr_status);
164#ifdef DWMAC_DMA_DEBUG
165 /* It displays the DMA process states (CSR5 register) */
166 show_tx_process_state(intr_status);
167 show_rx_process_state(intr_status);
168#endif
169 /* ABNORMAL interrupts */
170 if (unlikely(intr_status & DMA_STATUS_AIS)) {
171 DBG(INFO, "CSR5[15] DMA ABNORMAL IRQ: ");
172 if (unlikely(intr_status & DMA_STATUS_UNF)) {
173 DBG(INFO, "transmit underflow\n");
174 ret = tx_hard_error_bump_tc;
175 x->tx_undeflow_irq++;
176 }
177 if (unlikely(intr_status & DMA_STATUS_TJT)) {
178 DBG(INFO, "transmit jabber\n");
179 x->tx_jabber_irq++;
180 }
181 if (unlikely(intr_status & DMA_STATUS_OVF)) {
182 DBG(INFO, "recv overflow\n");
183 x->rx_overflow_irq++;
184 }
185 if (unlikely(intr_status & DMA_STATUS_RU)) {
186 DBG(INFO, "receive buffer unavailable\n");
187 x->rx_buf_unav_irq++;
188 }
189 if (unlikely(intr_status & DMA_STATUS_RPS)) {
190 DBG(INFO, "receive process stopped\n");
191 x->rx_process_stopped_irq++;
192 }
193 if (unlikely(intr_status & DMA_STATUS_RWT)) {
194 DBG(INFO, "receive watchdog\n");
195 x->rx_watchdog_irq++;
196 }
197 if (unlikely(intr_status & DMA_STATUS_ETI)) {
198 DBG(INFO, "transmit early interrupt\n");
199 x->tx_early_irq++;
200 }
201 if (unlikely(intr_status & DMA_STATUS_TPS)) {
202 DBG(INFO, "transmit process stopped\n");
203 x->tx_process_stopped_irq++;
204 ret = tx_hard_error;
205 }
206 if (unlikely(intr_status & DMA_STATUS_FBI)) {
207 DBG(INFO, "fatal bus error\n");
208 x->fatal_bus_error_irq++;
209 ret = tx_hard_error;
210 }
211 }
212 /* TX/RX NORMAL interrupts */
213 if (intr_status & DMA_STATUS_NIS) {
214 x->normal_irq_n++;
215 if (likely((intr_status & DMA_STATUS_RI) ||
216 (intr_status & (DMA_STATUS_TI))))
217 ret = handle_tx_rx;
218 }
219 /* Optional hardware blocks, interrupts should be disabled */
220 if (unlikely(intr_status &
221 (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
222 pr_info("%s: unexpected status %08x\n", __func__, intr_status);
223 /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
224 writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
225
226 DBG(INFO, "\n\n");
227 return ret;
228}
229
230
231void stmmac_set_mac_addr(unsigned long ioaddr, u8 addr[6],
232 unsigned int high, unsigned int low)
233{
234 unsigned long data;
235
236 data = (addr[5] << 8) | addr[4];
237 writel(data, ioaddr + high);
238 data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
239 writel(data, ioaddr + low);
240
241 return;
242}
243
244void stmmac_get_mac_addr(unsigned long ioaddr, unsigned char *addr,
245 unsigned int high, unsigned int low)
246{
247 unsigned int hi_addr, lo_addr;
248
249 /* Read the MAC address from the hardware */
250 hi_addr = readl(ioaddr + high);
251 lo_addr = readl(ioaddr + low);
252
253 /* Extract the MAC address from the high and low words */
254 addr[0] = lo_addr & 0xff;
255 addr[1] = (lo_addr >> 8) & 0xff;
256 addr[2] = (lo_addr >> 16) & 0xff;
257 addr[3] = (lo_addr >> 24) & 0xff;
258 addr[4] = hi_addr & 0xff;
259 addr[5] = (hi_addr >> 8) & 0xff;
260
261 return;
262}
263