1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <linux/io.h>
20#include <linux/iopoll.h>
21#include "common.h"
22#include "dwmac_dma.h"
23
24#define GMAC_HI_REG_AE 0x80000000
25
26int dwmac_dma_reset(void __iomem *ioaddr)
27{
28 u32 value = readl(ioaddr + DMA_BUS_MODE);
29
30
31 value |= DMA_BUS_MODE_SFT_RESET;
32 writel(value, ioaddr + DMA_BUS_MODE);
33
34 return readl_poll_timeout(ioaddr + DMA_BUS_MODE, value,
35 !(value & DMA_BUS_MODE_SFT_RESET),
36 10000, 200000);
37}
38
39
40void dwmac_enable_dma_transmission(void __iomem *ioaddr)
41{
42 writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
43}
44
45void dwmac_enable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx)
46{
47 u32 value = readl(ioaddr + DMA_INTR_ENA);
48
49 if (rx)
50 value |= DMA_INTR_DEFAULT_RX;
51 if (tx)
52 value |= DMA_INTR_DEFAULT_TX;
53
54 writel(value, ioaddr + DMA_INTR_ENA);
55}
56
57void dwmac_disable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx)
58{
59 u32 value = readl(ioaddr + DMA_INTR_ENA);
60
61 if (rx)
62 value &= ~DMA_INTR_DEFAULT_RX;
63 if (tx)
64 value &= ~DMA_INTR_DEFAULT_TX;
65
66 writel(value, ioaddr + DMA_INTR_ENA);
67}
68
69void dwmac_dma_start_tx(void __iomem *ioaddr, u32 chan)
70{
71 u32 value = readl(ioaddr + DMA_CONTROL);
72 value |= DMA_CONTROL_ST;
73 writel(value, ioaddr + DMA_CONTROL);
74}
75
76void dwmac_dma_stop_tx(void __iomem *ioaddr, u32 chan)
77{
78 u32 value = readl(ioaddr + DMA_CONTROL);
79 value &= ~DMA_CONTROL_ST;
80 writel(value, ioaddr + DMA_CONTROL);
81}
82
83void dwmac_dma_start_rx(void __iomem *ioaddr, u32 chan)
84{
85 u32 value = readl(ioaddr + DMA_CONTROL);
86 value |= DMA_CONTROL_SR;
87 writel(value, ioaddr + DMA_CONTROL);
88}
89
90void dwmac_dma_stop_rx(void __iomem *ioaddr, u32 chan)
91{
92 u32 value = readl(ioaddr + DMA_CONTROL);
93 value &= ~DMA_CONTROL_SR;
94 writel(value, ioaddr + DMA_CONTROL);
95}
96
97#ifdef DWMAC_DMA_DEBUG
98static void show_tx_process_state(unsigned int status)
99{
100 unsigned int state;
101 state = (status & DMA_STATUS_TS_MASK) >> DMA_STATUS_TS_SHIFT;
102
103 switch (state) {
104 case 0:
105 pr_debug("- TX (Stopped): Reset or Stop command\n");
106 break;
107 case 1:
108 pr_debug("- TX (Running): Fetching the Tx desc\n");
109 break;
110 case 2:
111 pr_debug("- TX (Running): Waiting for end of tx\n");
112 break;
113 case 3:
114 pr_debug("- TX (Running): Reading the data "
115 "and queuing the data into the Tx buf\n");
116 break;
117 case 6:
118 pr_debug("- TX (Suspended): Tx Buff Underflow "
119 "or an unavailable Transmit descriptor\n");
120 break;
121 case 7:
122 pr_debug("- TX (Running): Closing Tx descriptor\n");
123 break;
124 default:
125 break;
126 }
127}
128
129static void show_rx_process_state(unsigned int status)
130{
131 unsigned int state;
132 state = (status & DMA_STATUS_RS_MASK) >> DMA_STATUS_RS_SHIFT;
133
134 switch (state) {
135 case 0:
136 pr_debug("- RX (Stopped): Reset or Stop command\n");
137 break;
138 case 1:
139 pr_debug("- RX (Running): Fetching the Rx desc\n");
140 break;
141 case 2:
142 pr_debug("- RX (Running): Checking for end of pkt\n");
143 break;
144 case 3:
145 pr_debug("- RX (Running): Waiting for Rx pkt\n");
146 break;
147 case 4:
148 pr_debug("- RX (Suspended): Unavailable Rx buf\n");
149 break;
150 case 5:
151 pr_debug("- RX (Running): Closing Rx descriptor\n");
152 break;
153 case 6:
154 pr_debug("- RX(Running): Flushing the current frame"
155 " from the Rx buf\n");
156 break;
157 case 7:
158 pr_debug("- RX (Running): Queuing the Rx frame"
159 " from the Rx buf into memory\n");
160 break;
161 default:
162 break;
163 }
164}
165#endif
166
167int dwmac_dma_interrupt(void __iomem *ioaddr,
168 struct stmmac_extra_stats *x, u32 chan, u32 dir)
169{
170 int ret = 0;
171
172 u32 intr_status = readl(ioaddr + DMA_STATUS);
173
174#ifdef DWMAC_DMA_DEBUG
175
176 pr_debug("%s: [CSR5: 0x%08x]\n", __func__, intr_status);
177 show_tx_process_state(intr_status);
178 show_rx_process_state(intr_status);
179#endif
180
181 if (dir == DMA_DIR_RX)
182 intr_status &= DMA_STATUS_MSK_RX;
183 else if (dir == DMA_DIR_TX)
184 intr_status &= DMA_STATUS_MSK_TX;
185
186
187 if (unlikely(intr_status & DMA_STATUS_AIS)) {
188 if (unlikely(intr_status & DMA_STATUS_UNF)) {
189 ret = tx_hard_error_bump_tc;
190 x->tx_undeflow_irq++;
191 }
192 if (unlikely(intr_status & DMA_STATUS_TJT))
193 x->tx_jabber_irq++;
194
195 if (unlikely(intr_status & DMA_STATUS_OVF))
196 x->rx_overflow_irq++;
197
198 if (unlikely(intr_status & DMA_STATUS_RU))
199 x->rx_buf_unav_irq++;
200 if (unlikely(intr_status & DMA_STATUS_RPS))
201 x->rx_process_stopped_irq++;
202 if (unlikely(intr_status & DMA_STATUS_RWT))
203 x->rx_watchdog_irq++;
204 if (unlikely(intr_status & DMA_STATUS_ETI))
205 x->tx_early_irq++;
206 if (unlikely(intr_status & DMA_STATUS_TPS)) {
207 x->tx_process_stopped_irq++;
208 ret = tx_hard_error;
209 }
210 if (unlikely(intr_status & DMA_STATUS_FBI)) {
211 x->fatal_bus_error_irq++;
212 ret = tx_hard_error;
213 }
214 }
215
216 if (likely(intr_status & DMA_STATUS_NIS)) {
217 x->normal_irq_n++;
218 if (likely(intr_status & DMA_STATUS_RI)) {
219 u32 value = readl(ioaddr + DMA_INTR_ENA);
220
221 if (likely(value & DMA_INTR_ENA_RIE)) {
222 x->rx_normal_irq_n++;
223 ret |= handle_rx;
224 }
225 }
226 if (likely(intr_status & DMA_STATUS_TI)) {
227 x->tx_normal_irq_n++;
228 ret |= handle_tx;
229 }
230 if (unlikely(intr_status & DMA_STATUS_ERI))
231 x->rx_early_irq++;
232 }
233
234 if (unlikely(intr_status &
235 (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
236 pr_warn("%s: unexpected status %08x\n", __func__, intr_status);
237
238
239 writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
240
241 return ret;
242}
243
244void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr)
245{
246 u32 csr6 = readl(ioaddr + DMA_CONTROL);
247 writel((csr6 | DMA_CONTROL_FTF), ioaddr + DMA_CONTROL);
248
249 do {} while ((readl(ioaddr + DMA_CONTROL) & DMA_CONTROL_FTF));
250}
251
252void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
253 unsigned int high, unsigned int low)
254{
255 unsigned long data;
256
257 data = (addr[5] << 8) | addr[4];
258
259
260
261
262 writel(data | GMAC_HI_REG_AE, ioaddr + high);
263 data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
264 writel(data, ioaddr + low);
265}
266EXPORT_SYMBOL_GPL(stmmac_set_mac_addr);
267
268
269void stmmac_set_mac(void __iomem *ioaddr, bool enable)
270{
271 u32 value = readl(ioaddr + MAC_CTRL_REG);
272
273 if (enable)
274 value |= MAC_ENABLE_RX | MAC_ENABLE_TX;
275 else
276 value &= ~(MAC_ENABLE_TX | MAC_ENABLE_RX);
277
278 writel(value, ioaddr + MAC_CTRL_REG);
279}
280
281void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
282 unsigned int high, unsigned int low)
283{
284 unsigned int hi_addr, lo_addr;
285
286
287 hi_addr = readl(ioaddr + high);
288 lo_addr = readl(ioaddr + low);
289
290
291 addr[0] = lo_addr & 0xff;
292 addr[1] = (lo_addr >> 8) & 0xff;
293 addr[2] = (lo_addr >> 16) & 0xff;
294 addr[3] = (lo_addr >> 24) & 0xff;
295 addr[4] = hi_addr & 0xff;
296 addr[5] = (hi_addr >> 8) & 0xff;
297}
298EXPORT_SYMBOL_GPL(stmmac_get_mac_addr);
299