1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
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
53
54
55
56
57
58
59
60
61
62 value = DMA_BUS_MODE_PBL | ((pbl << DMA_BUS_MODE_PBL_SHIFT) |
63 (pbl << DMA_BUS_MODE_RPBL_SHIFT));
64
65
66 if (fb)
67 value |= DMA_BUS_MODE_FB;
68
69
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 writel(burst_len, ioaddr + DMA_AXI_BUS_MODE);
96
97
98 writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
99
100
101
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
115
116
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
138 csr6 |= DMA_CONTROL_TSF;
139
140
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
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
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