1 /* $Id: pci_iommu.c,v 1.1 1999/08/30 10:00:47 davem Exp $
2 * pci_iommu.c: UltraSparc PCI controller IOM/STC support.
4 * Copyright (C) 1999 David S. Miller (davem@redhat.com)
9 #include <asm/scatterlist.h>
11 #define PCI_STC_CTXMATCH_ADDR(STC, CTX) \
12 ((STC)->strbuf_ctxmatch_base + ((CTX) << 3))
14 /* Accessing IOMMU and Streaming Buffer registers.
15 * REG parameter is a physical address. All registers
16 * are 64-bits in size.
18 #define pci_iommu_read(__reg) \
20 __asm__ __volatile__("ldxa [%1] %2, %0" \
22 : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
26 #define pci_iommu_write(__reg, __val) \
27 __asm__ __volatile__("stxa %0, [%1] %2" \
29 : "r" (__val), "r" (__reg), \
30 "i" (ASI_PHYS_BYPASS_EC_E))
32 /* Find a range of iommu mappings of size NPAGES in page
33 * table PGT. Return pointer to first iopte.
35 static iopte_t
*iommu_find_range(unsigned long npages
, iopte_t
*pgt
, int pgt_size
)
40 for (i
= 0; i
< pgt_size
; i
++) {
41 if (!iopte_val(pgt
[i
]) & IOPTE_VALID
) {
44 for (scan
= 1; scan
< npages
; scan
++) {
45 if (iopte_val(pgt
[i
+ scan
]) & IOPTE_VALID
) {
57 #define IOPTE_CONSISTANT(CTX, PADDR) \
58 (IOPTE_VALID | IOPTE_CACHE | IOPTE_WRITE | \
59 (((CTX) << 47) & IOPTE_CONTEXT) | \
60 ((PADDR) & IOPTE_PAGE))
62 #define IOPTE_STREAMING(CTX, PADDR) \
63 (IOPTE_CONSISTANT(CTX, PADDR) | IOPTE_STBUF)
65 #define IOPTE_INVALID 0UL
67 /* Map kernel buffer at ADDR of size SZ using consistant mode
68 * DMA for PCI device PDEV. Return 32-bit PCI DMA address.
70 u32
pci_map_consistant(struct pci_dev
*pdev
, void *addr
, int sz
)
72 struct pcidev_cookie
*pcp
= pdev
->sysdata
;
73 struct pci_iommu
*iommu
= &pcp
->pbm
->parent
->iommu
;
75 unsigned long flags
, npages
, oaddr
;
78 spin_lock_irqsave(&iommu
->lock
, flags
);
79 oaddr
= (unsigned long)addr
;
80 npages
= PAGE_ALIGN(oaddr
+ sz
) - (oaddr
& PAGE_MASK
);
81 npages
>>= PAGE_SHIFT
;
82 base
= iommu_find_range(npages
,
83 iommu
->page_table
, iommu
->page_table_sz
);
86 unsigned long i
, base_paddr
, ctx
;
88 ret
= (iommu
->page_table_map_base
+
89 ((base
- iommu
->page_table
) << PAGE_SHIFT
));
90 ret
|= (oaddr
& ~PAGE_MASK
);
91 base_paddr
= __pa(oaddr
& PAGE_MASK
);
93 if (iommu
->iommu_has_ctx_flush
)
94 ctx
= iommu
->iommu_cur_ctx
++;
95 for (i
= 0; i
< npages
; i
++, base
++, base_paddr
+= PAGE_SIZE
)
96 iopte_val(*base
) = IOPTE_CONSISTANT(ctx
, base_paddr
);
98 spin_unlock_irqrestore(&iommu
->lock
, flags
);
103 /* Unmap a consistant DMA translation. */
104 void pci_unmap_consistant(struct pci_dev
*pdev
, u32 bus_addr
, int sz
)
106 struct pcidev_cookie
*pcp
= pdev
->sysdata
;
107 struct pci_iommu
*iommu
= &pcp
->pbm
->parent
->iommu
;
109 unsigned long flags
, npages
, i
, ctx
;
111 spin_lock_irqsave(&iommu
->lock
, flags
);
112 npages
= PAGE_ALIGN(bus_addr
+ sz
) - (bus_addr
& PAGE_MASK
);
113 npages
>>= PAGE_SHIFT
;
114 base
= iommu
->page_table
+
115 ((bus_addr
- iommu
->page_table_map_base
) >> PAGE_SHIFT
);
117 /* Data for consistant mappings cannot enter the streaming
118 * buffers, so we only need to update the TSB and flush
119 * those entries from the IOMMU's TLB.
122 /* Step 1: Clear out the TSB entries. Save away
123 * the context if necessary.
126 if (iommu
->iommu_has_ctx_flush
)
127 ctx
= (iopte_val(*base
) & IOPTE_CONTEXT
) >> 47UL;
128 for (i
= 0; i
< npages
; i
++, base
++)
129 iopte_val(*base
) = IOPTE_INVALID
;
131 /* Step 2: Flush from IOMMU TLB. */
132 if (iommu
->iommu_has_ctx_flush
) {
133 pci_iommu_write(iommu
->iommu_ctxflush
, ctx
);
135 bus_addr
&= PAGE_MASK
;
136 for (i
= 0; i
< npages
; i
++, bus_addr
+= PAGE_SIZE
)
137 pci_iommu_write(iommu
->iommu_flush
, bus_addr
);
140 /* Step 3: Ensure completion of previous PIO writes. */
141 (void) pci_iommu_read(iommu
->write_complete_reg
);
143 spin_unlock_irqrestore(&iommu
->lock
, flags
);
146 /* Map a single buffer at PTR of SZ bytes for PCI DMA
149 u32
pci_map_single(struct pci_dev
*pdev
, void *ptr
, int sz
)
151 struct pcidev_cookie
*pcp
= pdev
->sysdata
;
152 struct pci_iommu
*iommu
= &pcp
->pbm
->parent
->iommu
;
154 unsigned long flags
, npages
, oaddr
;
157 spin_lock_irqsave(&iommu
->lock
, flags
);
158 oaddr
= (unsigned long)ptr
;
159 npages
= PAGE_ALIGN(oaddr
+ sz
) - (oaddr
& PAGE_MASK
);
160 npages
>>= PAGE_SHIFT
;
161 base
= iommu_find_range(npages
,
162 iommu
->page_table
, iommu
->page_table_sz
);
165 unsigned long i
, base_paddr
, ctx
;
167 ret
= (iommu
->page_table_map_base
+
168 ((base
- iommu
->page_table
) << PAGE_SHIFT
));
169 ret
|= (oaddr
& ~PAGE_MASK
);
170 base_paddr
= __pa(oaddr
& PAGE_MASK
);
172 if (iommu
->iommu_has_ctx_flush
)
173 ctx
= iommu
->iommu_cur_ctx
++;
174 for (i
= 0; i
< npages
; i
++, base
++, base_paddr
+= PAGE_SIZE
)
175 iopte_val(*base
) = IOPTE_STREAMING(ctx
, base_paddr
);
177 spin_unlock_irqrestore(&iommu
->lock
, flags
);
182 /* Unmap a single streaming mode DMA translation. */
183 void pci_unmap_single(struct pci_dev
*pdev
, u32 bus_addr
, int sz
)
185 struct pcidev_cookie
*pcp
= pdev
->sysdata
;
186 struct pci_iommu
*iommu
= &pcp
->pbm
->parent
->iommu
;
187 struct pci_strbuf
*strbuf
= &pcp
->pbm
->stc
;
189 unsigned long flags
, npages
, i
, ctx
;
191 spin_lock_irqsave(&iommu
->lock
, flags
);
192 npages
= PAGE_ALIGN(bus_addr
+ sz
) - (bus_addr
& PAGE_MASK
);
193 npages
>>= PAGE_SHIFT
;
194 base
= iommu
->page_table
+
195 ((bus_addr
- iommu
->page_table_map_base
) >> PAGE_SHIFT
);
196 bus_addr
&= PAGE_MASK
;
198 /* Step 1: Record the context, if any. */
200 if (iommu
->iommu_has_ctx_flush
)
201 ctx
= (iopte_val(*base
) & IOPTE_CONTEXT
) >> 47UL;
203 /* Step 2: Kick data out of streaming buffers if necessary. */
204 if (strbuf
->strbuf_enabled
) {
205 u32 vaddr
= bus_addr
;
207 PCI_STC_FLUSHFLAG_INIT(strbuf
);
208 if (strbuf
->strbuf_has_ctx_flush
&&
209 iommu
->iommu_has_ctx_flush
) {
210 unsigned long matchreg
, flushreg
;
212 flushreg
= strbuf
->strbuf_ctxflush
;
213 matchreg
= PCI_STC_CTXMATCH_ADDR(strbuf
, ctx
);
215 pci_iommu_write(flushreg
, ctx
);
216 } while(((long)pci_iommu_read(matchreg
)) < 0L);
218 for (i
= 0; i
< npages
; i
++, vaddr
+= PAGE_SIZE
)
219 pci_iommu_write(strbuf
->strbuf_pflush
, vaddr
);
222 pci_iommu_write(strbuf
->strbuf_fsync
, strbuf
->strbuf_flushflag_pa
);
223 (void) pci_iommu_read(iommu
->write_complete_reg
);
224 while (!PCI_STC_FLUSHFLAG_SET(strbuf
))
228 /* Step 3: Clear out TSB entries. */
229 for (i
= 0; i
< npages
; i
++, base
++)
230 iopte_val(*base
) = IOPTE_INVALID
;
232 /* Step 4: Flush the IOMMU TLB. */
233 if (iommu
->iommu_has_ctx_flush
) {
234 pci_iommu_write(iommu
->iommu_ctxflush
, ctx
);
236 for (i
= 0; i
< npages
; i
++, bus_addr
+= PAGE_SIZE
)
237 pci_iommu_write(iommu
->iommu_flush
, bus_addr
);
240 /* Step 5: Ensure completion of previous PIO writes. */
241 (void) pci_iommu_read(iommu
->write_complete_reg
);
243 spin_unlock_irqrestore(&iommu
->lock
, flags
);
246 /* Map a set of buffers described by SGLIST with NELEMS array
247 * elements in streaming mode for PCI DMA.
249 void pci_map_sg(struct pci_dev
*pdev
, struct scatterlist
*sglist
, int nelems
)
251 struct pcidev_cookie
*pcp
= pdev
->sysdata
;
252 struct pci_iommu
*iommu
= &pcp
->pbm
->parent
->iommu
;
253 unsigned long flags
, ctx
, i
;
255 spin_lock_irqsave(&iommu
->lock
, flags
);
257 /* Step 1: Choose a context if necessary. */
259 if (iommu
->iommu_has_ctx_flush
)
260 ctx
= iommu
->iommu_cur_ctx
++;
262 /* Step 2: Create the mappings. */
263 for (i
= 0; i
< nelems
; i
++) {
264 unsigned long oaddr
, npages
;
267 oaddr
= (unsigned long)sglist
[i
].address
;
268 npages
= PAGE_ALIGN(oaddr
+ sglist
[i
].length
) - (oaddr
& PAGE_MASK
);
269 npages
>>= PAGE_SHIFT
;
270 base
= iommu_find_range(npages
,
271 iommu
->page_table
, iommu
->page_table_sz
);
273 unsigned long j
, base_paddr
;
276 dvma_addr
= (iommu
->page_table_map_base
+
277 ((base
- iommu
->page_table
) << PAGE_SHIFT
));
278 dvma_addr
|= (oaddr
& ~PAGE_MASK
);
279 sglist
[i
].dvma_address
= dvma_addr
;
280 sglist
[i
].dvma_length
= sglist
[i
].length
;
281 base_paddr
= __pa(oaddr
& PAGE_MASK
);
282 for (j
= 0; j
< npages
; j
++, base
++, base_paddr
+= PAGE_SIZE
)
283 iopte_val(*base
) = IOPTE_STREAMING(ctx
, base_paddr
);
285 sglist
[i
].dvma_address
= 0;
286 sglist
[i
].dvma_length
= 0;
290 spin_unlock_irqrestore(&iommu
->lock
, flags
);
293 /* Unmap a set of streaming mode DMA translations. */
294 void pci_unmap_sg(struct pci_dev
*pdev
, struct scatterlist
*sglist
, int nelems
)
296 struct pcidev_cookie
*pcp
= pdev
->sysdata
;
297 struct pci_iommu
*iommu
= &pcp
->pbm
->parent
->iommu
;
298 struct pci_strbuf
*strbuf
= &pcp
->pbm
->stc
;
299 unsigned long flags
, ctx
, i
;
301 spin_lock_irqsave(&iommu
->lock
, flags
);
303 /* Step 1: Record the context, if any. */
305 if (iommu
->iommu_has_ctx_flush
) {
308 iopte
= iommu
->page_table
+
309 ((sglist
[0].dvma_address
- iommu
->page_table_map_base
) >> PAGE_SHIFT
);
310 ctx
= (iopte_val(*iopte
) & IOPTE_CONTEXT
) >> 47UL;
313 /* Step 2: Kick data out of streaming buffers if necessary. */
314 if (strbuf
->strbuf_enabled
) {
315 PCI_STC_FLUSHFLAG_INIT(strbuf
);
316 if (strbuf
->strbuf_has_ctx_flush
&&
317 iommu
->iommu_has_ctx_flush
) {
318 unsigned long matchreg
, flushreg
;
320 flushreg
= strbuf
->strbuf_ctxflush
;
321 matchreg
= PCI_STC_CTXMATCH_ADDR(strbuf
, ctx
);
323 pci_iommu_write(flushreg
, ctx
);
324 } while(((long)pci_iommu_read(matchreg
)) < 0L);
326 for (i
= 0; i
< nelems
; i
++) {
327 unsigned long j
, npages
;
330 j
= sglist
[i
].dvma_length
;
333 vaddr
= sglist
[i
].dvma_address
;
334 npages
= PAGE_ALIGN(vaddr
+ j
) - (vaddr
& PAGE_MASK
);
335 npages
>>= PAGE_SHIFT
;
337 for (j
= 0; j
< npages
; j
++, vaddr
+= PAGE_SIZE
)
338 pci_iommu_write(strbuf
->strbuf_pflush
, vaddr
);
341 pci_iommu_write(strbuf
->strbuf_fsync
, strbuf
->strbuf_flushflag_pa
);
342 (void) pci_iommu_read(iommu
->write_complete_reg
);
343 while (!PCI_STC_FLUSHFLAG_SET(strbuf
))
348 /* Step 3: Clear out TSB entries. */
349 for (i
= 0; i
< nelems
; i
++) {
350 unsigned long j
, npages
;
354 j
= sglist
[i
].dvma_length
;
357 vaddr
= sglist
[i
].dvma_address
;
358 npages
= PAGE_ALIGN(vaddr
+ j
) - (vaddr
& PAGE_MASK
);
359 npages
>>= PAGE_SHIFT
;
360 base
= iommu
->page_table
+
361 ((vaddr
- iommu
->page_table_map_base
) >> PAGE_SHIFT
);
362 for (j
= 0; j
< npages
; j
++, base
++)
363 iopte_val(*base
) = IOPTE_INVALID
;
366 /* Step 4: Flush the IOMMU TLB. */
367 if (iommu
->iommu_has_ctx_flush
) {
368 pci_iommu_write(iommu
->iommu_ctxflush
, ctx
);
370 for (i
= 0; i
< nelems
; i
++) {
371 unsigned long j
, npages
;
374 j
= sglist
[i
].dvma_length
;
377 vaddr
= sglist
[i
].dvma_address
;
378 npages
= PAGE_ALIGN(vaddr
+ j
) - (vaddr
& PAGE_MASK
);
379 npages
>>= PAGE_SHIFT
;
380 for (j
= 0; j
< npages
; j
++, vaddr
+= PAGE_SIZE
)
381 pci_iommu_write(iommu
->iommu_flush
, vaddr
);
385 /* Step 5: Ensure completion of previous PIO writes. */
386 (void) pci_iommu_read(iommu
->write_complete_reg
);
388 spin_unlock_irqrestore(&iommu
->lock
, flags
);
391 /* Make physical memory consistant for a single
392 * streaming mode DMA translation after a transfer.
394 void pci_dma_sync_single(struct pci_dev
*pdev
, u32 bus_addr
, int sz
)
396 struct pcidev_cookie
*pcp
= pdev
->sysdata
;
397 struct pci_iommu
*iommu
= &pcp
->pbm
->parent
->iommu
;
398 struct pci_strbuf
*strbuf
= &pcp
->pbm
->stc
;
399 unsigned long flags
, ctx
, npages
;
401 if (!strbuf
->strbuf_enabled
)
404 spin_lock_irqsave(&iommu
->lock
, flags
);
406 npages
= PAGE_ALIGN(bus_addr
+ sz
) - (bus_addr
& PAGE_MASK
);
407 npages
>>= PAGE_SHIFT
;
408 bus_addr
&= PAGE_MASK
;
410 /* Step 1: Record the context, if any. */
412 if (iommu
->iommu_has_ctx_flush
&&
413 strbuf
->strbuf_has_ctx_flush
) {
416 iopte
= iommu
->page_table
+
417 ((bus_addr
- iommu
->page_table_map_base
)>>PAGE_SHIFT
);
418 ctx
= (iopte_val(*iopte
) & IOPTE_CONTEXT
) >> 47UL;
421 /* Step 2: Kick data out of streaming buffers. */
422 PCI_STC_FLUSHFLAG_INIT(strbuf
);
423 if (iommu
->iommu_has_ctx_flush
&&
424 strbuf
->strbuf_has_ctx_flush
) {
425 unsigned long matchreg
, flushreg
;
427 flushreg
= strbuf
->strbuf_ctxflush
;
428 matchreg
= PCI_STC_CTXMATCH_ADDR(strbuf
, ctx
);
430 pci_iommu_write(flushreg
, ctx
);
431 } while(((long)pci_iommu_read(matchreg
)) < 0L);
435 for (i
= 0; i
< npages
; i
++, bus_addr
+= PAGE_SIZE
)
436 pci_iommu_write(strbuf
->strbuf_pflush
, bus_addr
);
439 /* Step 3: Perform flush synchronization sequence. */
440 pci_iommu_write(strbuf
->strbuf_fsync
, strbuf
->strbuf_flushflag_pa
);
441 (void) pci_iommu_read(iommu
->write_complete_reg
);
442 while (!PCI_STC_FLUSHFLAG_SET(strbuf
))
445 spin_unlock_irqrestore(&iommu
->lock
, flags
);
448 /* Make physical memory consistant for a set of streaming
449 * mode DMA translations after a transfer.
451 void pci_dma_sync_sg(struct pci_dev
*pdev
, struct scatterlist
*sglist
, int nelems
)
453 struct pcidev_cookie
*pcp
= pdev
->sysdata
;
454 struct pci_iommu
*iommu
= &pcp
->pbm
->parent
->iommu
;
455 struct pci_strbuf
*strbuf
= &pcp
->pbm
->stc
;
456 unsigned long flags
, ctx
;
458 if (!strbuf
->strbuf_enabled
)
461 spin_lock_irqsave(&iommu
->lock
, flags
);
463 /* Step 1: Record the context, if any. */
465 if (iommu
->iommu_has_ctx_flush
&&
466 strbuf
->strbuf_has_ctx_flush
) {
469 iopte
= iommu
->page_table
+
470 ((sglist
[0].dvma_address
- iommu
->page_table_map_base
) >> PAGE_SHIFT
);
471 ctx
= (iopte_val(*iopte
) & IOPTE_CONTEXT
) >> 47UL;
474 /* Step 2: Kick data out of streaming buffers. */
475 PCI_STC_FLUSHFLAG_INIT(strbuf
);
476 if (iommu
->iommu_has_ctx_flush
&&
477 strbuf
->strbuf_has_ctx_flush
) {
478 unsigned long matchreg
, flushreg
;
480 flushreg
= strbuf
->strbuf_ctxflush
;
481 matchreg
= PCI_STC_CTXMATCH_ADDR(strbuf
, ctx
);
483 pci_iommu_write(flushreg
, ctx
);
484 } while (((long)pci_iommu_read(matchreg
)) < 0L);
488 for(i
= 0; i
< nelems
; i
++) {
489 unsigned long bus_addr
, npages
, j
;
491 j
= sglist
[i
].dvma_length
;
494 bus_addr
= sglist
[i
].dvma_address
;
495 npages
= PAGE_ALIGN(bus_addr
+ j
) - (bus_addr
& PAGE_MASK
);
496 npages
>>= PAGE_SHIFT
;
497 bus_addr
&= PAGE_MASK
;
498 for(j
= 0; i
< npages
; i
++, bus_addr
+= PAGE_SIZE
)
499 pci_iommu_write(strbuf
->strbuf_pflush
, bus_addr
);
503 /* Step 3: Perform flush synchronization sequence. */
504 pci_iommu_write(strbuf
->strbuf_fsync
, strbuf
->strbuf_flushflag_pa
);
505 (void) pci_iommu_read(iommu
->write_complete_reg
);
506 while (!PCI_STC_FLUSHFLAG_SET(strbuf
))
509 spin_unlock_irqrestore(&iommu
->lock
, flags
);