1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/types.h>
15#include <linux/mm.h>
16#include <linux/module.h>
17#include <linux/string.h>
18#include <linux/dma-mapping.h>
19#include <linux/platform_device.h>
20#include <linux/scatterlist.h>
21
22#include <linux/cache.h>
23#include <linux/io.h>
24
25#include <asm/octeon/octeon.h>
26#include <asm/octeon/cvmx-npi-defs.h>
27#include <asm/octeon/cvmx-pci-defs.h>
28
29#include <dma-coherence.h>
30
31#ifdef CONFIG_PCI
32#include <asm/octeon/pci-octeon.h>
33#endif
34
35#define BAR2_PCI_ADDRESS 0x8000000000ul
36
37struct bar1_index_state {
38 int16_t ref_count;
39 uint16_t address_bits;
40
41};
42
43#ifdef CONFIG_PCI
44static DEFINE_SPINLOCK(bar1_lock);
45static struct bar1_index_state bar1_state[32];
46#endif
47
48dma_addr_t octeon_map_dma_mem(struct device *dev, void *ptr, size_t size)
49{
50#ifndef CONFIG_PCI
51
52
53 mb();
54 return virt_to_phys(ptr);
55#else
56 unsigned long flags;
57 uint64_t dma_mask;
58 int64_t start_index;
59 dma_addr_t result = -1;
60 uint64_t physical = virt_to_phys(ptr);
61 int64_t index;
62
63 mb();
64
65
66
67
68
69
70 if (dev) {
71 dma_mask = dev->coherent_dma_mask;
72 if (dev->dma_mask)
73 dma_mask = *dev->dma_mask;
74 } else {
75 dma_mask = 0xfffffffful;
76 }
77
78
79
80
81
82 if (!dev || dev->bus == &platform_bus_type)
83 return physical;
84
85 switch (octeon_dma_bar_type) {
86 case OCTEON_DMA_BAR_TYPE_PCIE:
87 if (unlikely(physical < (16ul << 10)))
88 panic("dma_map_single: Not allowed to map first 16KB."
89 " It interferes with BAR0 special area\n");
90 else if ((physical + size >= (256ul << 20)) &&
91 (physical < (512ul << 20)))
92 panic("dma_map_single: Not allowed to map bootbus\n");
93 else if ((physical + size >= 0x400000000ull) &&
94 physical < 0x410000000ull)
95 panic("dma_map_single: "
96 "Attempt to map illegal memory address 0x%llx\n",
97 physical);
98 else if (physical >= 0x420000000ull)
99 panic("dma_map_single: "
100 "Attempt to map illegal memory address 0x%llx\n",
101 physical);
102 else if ((physical + size >=
103 (4ull<<30) - (OCTEON_PCI_BAR1_HOLE_SIZE<<20))
104 && physical < (4ull<<30))
105 pr_warning("dma_map_single: Warning: "
106 "Mapping memory address that might "
107 "conflict with devices 0x%llx-0x%llx\n",
108 physical, physical+size-1);
109
110 if ((physical >= 0x410000000ull) && physical < 0x420000000ull)
111 result = physical - 0x400000000ull;
112 else
113 result = physical;
114 if (((result+size-1) & dma_mask) != result+size-1)
115 panic("dma_map_single: Attempt to map address "
116 "0x%llx-0x%llx, which can't be accessed "
117 "according to the dma mask 0x%llx\n",
118 physical, physical+size-1, dma_mask);
119 goto done;
120
121 case OCTEON_DMA_BAR_TYPE_BIG:
122#ifdef CONFIG_64BIT
123
124 if (dma_mask > BAR2_PCI_ADDRESS) {
125 result = physical + BAR2_PCI_ADDRESS;
126 goto done;
127 }
128#endif
129 if (unlikely(physical < (4ul << 10))) {
130 panic("dma_map_single: Not allowed to map first 4KB. "
131 "It interferes with BAR0 special area\n");
132 } else if (physical < (256ul << 20)) {
133 if (unlikely(physical + size > (256ul << 20)))
134 panic("dma_map_single: Requested memory spans "
135 "Bar0 0:256MB and bootbus\n");
136 result = physical;
137 goto done;
138 } else if (unlikely(physical < (512ul << 20))) {
139 panic("dma_map_single: Not allowed to map bootbus\n");
140 } else if (physical < (2ul << 30)) {
141 if (unlikely(physical + size > (2ul << 30)))
142 panic("dma_map_single: Requested memory spans "
143 "Bar0 512MB:2GB and BAR1\n");
144 result = physical;
145 goto done;
146 } else if (physical < (2ul << 30) + (128 << 20)) {
147
148 } else if (physical <
149 (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20)) {
150 if (unlikely
151 (physical + size >
152 (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20)))
153 panic("dma_map_single: Requested memory "
154 "extends past Bar1 (4GB-%luMB)\n",
155 OCTEON_PCI_BAR1_HOLE_SIZE);
156 result = physical;
157 goto done;
158 } else if ((physical >= 0x410000000ull) &&
159 (physical < 0x420000000ull)) {
160 if (unlikely(physical + size > 0x420000000ull))
161 panic("dma_map_single: Requested memory spans "
162 "non existant memory\n");
163
164
165 result = physical - 0x400000000ull;
166 goto done;
167 } else {
168
169 }
170 break;
171
172 case OCTEON_DMA_BAR_TYPE_SMALL:
173#ifdef CONFIG_64BIT
174
175 if (dma_mask > BAR2_PCI_ADDRESS) {
176 result = physical + BAR2_PCI_ADDRESS;
177 goto done;
178 }
179#endif
180
181 break;
182
183 default:
184 panic("dma_map_single: Invalid octeon_dma_bar_type\n");
185 }
186
187
188
189 if (unlikely((physical >> 22) != ((physical + size - 1) >> 22)))
190 panic("dma_map_single: "
191 "Requested memory spans more than one Bar1 entry\n");
192
193 if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG)
194 start_index = 31;
195 else if (unlikely(dma_mask < (1ul << 27)))
196 start_index = (dma_mask >> 22);
197 else
198 start_index = 31;
199
200
201 spin_lock_irqsave(&bar1_lock, flags);
202
203
204 for (index = start_index; index >= 0; index--) {
205 if ((bar1_state[index].address_bits == physical >> 22) &&
206 (bar1_state[index].ref_count)) {
207
208 bar1_state[index].ref_count++;
209 if (unlikely(bar1_state[index].ref_count < 0))
210 panic("dma_map_single: "
211 "Bar1[%d] reference count overflowed\n",
212 (int) index);
213 result = (index << 22) | (physical & ((1 << 22) - 1));
214
215 if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG)
216 result += 2ul << 30;
217 goto done_unlock;
218 }
219 }
220
221
222 for (index = start_index; index >= 0; index--) {
223 if (unlikely(bar1_state[index].ref_count == 0)) {
224 union cvmx_pci_bar1_indexx bar1_index;
225
226 bar1_state[index].ref_count = 1;
227 bar1_state[index].address_bits = physical >> 22;
228 bar1_index.u32 = 0;
229
230 bar1_index.s.addr_idx = physical >> 22;
231
232 bar1_index.s.ca = 1;
233
234 bar1_index.s.end_swp = 1;
235
236 bar1_index.s.addr_v = 1;
237 octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index),
238 bar1_index.u32);
239
240 result = (index << 22) | (physical & ((1 << 22) - 1));
241
242 if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG)
243 result += 2ul << 30;
244 goto done_unlock;
245 }
246 }
247
248 pr_err("dma_map_single: "
249 "Can't find empty BAR1 index for physical mapping 0x%llx\n",
250 (unsigned long long) physical);
251
252done_unlock:
253 spin_unlock_irqrestore(&bar1_lock, flags);
254done:
255 pr_debug("dma_map_single 0x%llx->0x%llx\n", physical, result);
256 return result;
257#endif
258}
259
260void octeon_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
261{
262#ifndef CONFIG_PCI
263
264
265
266
267 return;
268#else
269 unsigned long flags;
270 uint64_t index;
271
272
273
274
275
276 if (dev->bus == &platform_bus_type)
277 return;
278
279 switch (octeon_dma_bar_type) {
280 case OCTEON_DMA_BAR_TYPE_PCIE:
281
282 goto done;
283
284 case OCTEON_DMA_BAR_TYPE_BIG:
285#ifdef CONFIG_64BIT
286
287 if (dma_addr >= BAR2_PCI_ADDRESS)
288 goto done;
289#endif
290 if (unlikely(dma_addr < (4ul << 10)))
291 panic("dma_unmap_single: Unexpect DMA address 0x%llx\n",
292 dma_addr);
293 else if (dma_addr < (2ul << 30))
294
295 goto done;
296 else if (dma_addr < (2ul << 30) + (128ul << 20))
297
298 index = (dma_addr - (2ul << 30)) >> 22;
299 else if (dma_addr <
300 (4ul << 30) - (OCTEON_PCI_BAR1_HOLE_SIZE << 20))
301 goto done;
302 else
303 panic("dma_unmap_single: Unexpect DMA address 0x%llx\n",
304 dma_addr);
305
306 break;
307
308 case OCTEON_DMA_BAR_TYPE_SMALL:
309#ifdef CONFIG_64BIT
310
311 if (dma_addr >= BAR2_PCI_ADDRESS)
312 goto done;
313#endif
314 index = dma_addr >> 22;
315
316 break;
317
318 default:
319 panic("dma_unmap_single: Invalid octeon_dma_bar_type\n");
320 }
321
322 if (unlikely(index > 31))
323 panic("dma_unmap_single: "
324 "Attempt to unmap an invalid address (0x%llx)\n",
325 dma_addr);
326
327 spin_lock_irqsave(&bar1_lock, flags);
328 bar1_state[index].ref_count--;
329 if (bar1_state[index].ref_count == 0)
330 octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), 0);
331 else if (unlikely(bar1_state[index].ref_count < 0))
332 panic("dma_unmap_single: Bar1[%u] reference count < 0\n",
333 (int) index);
334 spin_unlock_irqrestore(&bar1_lock, flags);
335done:
336 pr_debug("dma_unmap_single 0x%llx\n", dma_addr);
337 return;
338#endif
339}
340