2 * io-unit.c: IO-UNIT specific routines for memory management.
4 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
7 #include <linux/kernel.h>
8 #include <linux/init.h>
9 #include <linux/slab.h>
10 #include <linux/spinlock.h>
12 #include <linux/highmem.h> /* pte_offset_map => kmap_atomic */
13 #include <linux/bitops.h>
14 #include <linux/scatterlist.h>
16 #include <linux/of_device.h>
18 #include <asm/pgalloc.h>
19 #include <asm/pgtable.h>
21 #include <asm/io-unit.h>
23 #include <asm/cacheflush.h>
24 #include <asm/tlbflush.h>
26 #include <asm/oplib.h>
30 /* #define IOUNIT_DEBUG */
32 #define IOD(x) printk(x)
34 #define IOD(x) do { } while (0)
37 #define IOPERM (IOUPTE_CACHE | IOUPTE_WRITE | IOUPTE_VALID)
38 #define MKIOPTE(phys) __iopte((((phys)>>4) & IOUPTE_PAGE) | IOPERM)
40 static void __init
iounit_iommu_init(struct platform_device
*op
)
42 struct iounit_struct
*iounit
;
44 iopte_t __iomem
*xptend
;
46 iounit
= kzalloc(sizeof(struct iounit_struct
), GFP_ATOMIC
);
48 prom_printf("SUN4D: Cannot alloc iounit, halting.\n");
52 iounit
->limit
[0] = IOUNIT_BMAP1_START
;
53 iounit
->limit
[1] = IOUNIT_BMAP2_START
;
54 iounit
->limit
[2] = IOUNIT_BMAPM_START
;
55 iounit
->limit
[3] = IOUNIT_BMAPM_END
;
56 iounit
->rotor
[1] = IOUNIT_BMAP2_START
;
57 iounit
->rotor
[2] = IOUNIT_BMAPM_START
;
59 xpt
= of_ioremap(&op
->resource
[2], 0, PAGE_SIZE
* 16, "XPT");
61 prom_printf("SUN4D: Cannot map External Page Table.");
65 op
->dev
.archdata
.iommu
= iounit
;
66 iounit
->page_table
= xpt
;
67 spin_lock_init(&iounit
->lock
);
69 xptend
= iounit
->page_table
+ (16 * PAGE_SIZE
) / sizeof(iopte_t
);
70 for (; xpt
< xptend
; xpt
++)
74 static int __init
iounit_init(void)
76 extern void sun4d_init_sbi_irq(void);
77 struct device_node
*dp
;
79 for_each_node_by_name(dp
, "sbi") {
80 struct platform_device
*op
= of_find_device_by_node(dp
);
82 iounit_iommu_init(op
);
83 of_propagate_archdata(op
);
91 subsys_initcall(iounit_init
);
93 /* One has to hold iounit->lock to call this */
94 static unsigned long iounit_get_area(struct iounit_struct
*iounit
, unsigned long vaddr
, int size
)
97 unsigned long rotor
, scan
, limit
;
100 npages
= ((vaddr
& ~PAGE_MASK
) + size
+ (PAGE_SIZE
-1)) >> PAGE_SHIFT
;
102 /* A tiny bit of magic ingredience :) */
104 case 1: i
= 0x0231; break;
105 case 2: i
= 0x0132; break;
106 default: i
= 0x0213; break;
109 IOD(("iounit_get_area(%08lx,%d[%d])=", vaddr
, size
, npages
));
112 rotor
= iounit
->rotor
[j
- 1];
113 limit
= iounit
->limit
[j
];
115 nexti
: scan
= find_next_zero_bit(iounit
->bmap
, limit
, scan
);
116 if (scan
+ npages
> limit
) {
117 if (limit
!= rotor
) {
119 scan
= iounit
->limit
[j
- 1];
124 panic("iounit_get_area: Couldn't find free iopte slots for (%08lx,%d)\n", vaddr
, size
);
127 for (k
= 1, scan
++; k
< npages
; k
++)
128 if (test_bit(scan
++, iounit
->bmap
))
130 iounit
->rotor
[j
- 1] = (scan
< limit
) ? scan
: iounit
->limit
[j
- 1];
132 iopte
= MKIOPTE(__pa(vaddr
& PAGE_MASK
));
133 vaddr
= IOUNIT_DMA_BASE
+ (scan
<< PAGE_SHIFT
) + (vaddr
& ~PAGE_MASK
);
134 for (k
= 0; k
< npages
; k
++, iopte
= __iopte(iopte_val(iopte
) + 0x100), scan
++) {
135 set_bit(scan
, iounit
->bmap
);
136 sbus_writel(iopte_val(iopte
), &iounit
->page_table
[scan
]);
138 IOD(("%08lx\n", vaddr
));
142 static __u32
iounit_get_scsi_one(struct device
*dev
, char *vaddr
, unsigned long len
)
144 struct iounit_struct
*iounit
= dev
->archdata
.iommu
;
145 unsigned long ret
, flags
;
147 spin_lock_irqsave(&iounit
->lock
, flags
);
148 ret
= iounit_get_area(iounit
, (unsigned long)vaddr
, len
);
149 spin_unlock_irqrestore(&iounit
->lock
, flags
);
153 static void iounit_get_scsi_sgl(struct device
*dev
, struct scatterlist
*sg
, int sz
)
155 struct iounit_struct
*iounit
= dev
->archdata
.iommu
;
158 /* FIXME: Cache some resolved pages - often several sg entries are to the same page */
159 spin_lock_irqsave(&iounit
->lock
, flags
);
162 sg
->dma_address
= iounit_get_area(iounit
, (unsigned long) sg_virt(sg
), sg
->length
);
163 sg
->dma_length
= sg
->length
;
166 spin_unlock_irqrestore(&iounit
->lock
, flags
);
169 static void iounit_release_scsi_one(struct device
*dev
, __u32 vaddr
, unsigned long len
)
171 struct iounit_struct
*iounit
= dev
->archdata
.iommu
;
174 spin_lock_irqsave(&iounit
->lock
, flags
);
175 len
= ((vaddr
& ~PAGE_MASK
) + len
+ (PAGE_SIZE
-1)) >> PAGE_SHIFT
;
176 vaddr
= (vaddr
- IOUNIT_DMA_BASE
) >> PAGE_SHIFT
;
177 IOD(("iounit_release %08lx-%08lx\n", (long)vaddr
, (long)len
+vaddr
));
178 for (len
+= vaddr
; vaddr
< len
; vaddr
++)
179 clear_bit(vaddr
, iounit
->bmap
);
180 spin_unlock_irqrestore(&iounit
->lock
, flags
);
183 static void iounit_release_scsi_sgl(struct device
*dev
, struct scatterlist
*sg
, int sz
)
185 struct iounit_struct
*iounit
= dev
->archdata
.iommu
;
187 unsigned long vaddr
, len
;
189 spin_lock_irqsave(&iounit
->lock
, flags
);
192 len
= ((sg
->dma_address
& ~PAGE_MASK
) + sg
->length
+ (PAGE_SIZE
-1)) >> PAGE_SHIFT
;
193 vaddr
= (sg
->dma_address
- IOUNIT_DMA_BASE
) >> PAGE_SHIFT
;
194 IOD(("iounit_release %08lx-%08lx\n", (long)vaddr
, (long)len
+vaddr
));
195 for (len
+= vaddr
; vaddr
< len
; vaddr
++)
196 clear_bit(vaddr
, iounit
->bmap
);
199 spin_unlock_irqrestore(&iounit
->lock
, flags
);
203 static int iounit_map_dma_area(struct device
*dev
, dma_addr_t
*pba
, unsigned long va
, unsigned long addr
, int len
)
205 struct iounit_struct
*iounit
= dev
->archdata
.iommu
;
206 unsigned long page
, end
;
208 iopte_t __iomem
*iopte
;
212 dvma_prot
= __pgprot(SRMMU_CACHE
| SRMMU_ET_PTE
| SRMMU_PRIV
);
213 end
= PAGE_ALIGN((addr
+ len
));
222 pgdp
= pgd_offset(&init_mm
, addr
);
223 pmdp
= pmd_offset(pgdp
, addr
);
224 ptep
= pte_offset_map(pmdp
, addr
);
226 set_pte(ptep
, mk_pte(virt_to_page(page
), dvma_prot
));
228 i
= ((addr
- IOUNIT_DMA_BASE
) >> PAGE_SHIFT
);
230 iopte
= iounit
->page_table
+ i
;
231 sbus_writel(iopte_val(MKIOPTE(__pa(page
))), iopte
);
242 static void iounit_unmap_dma_area(struct device
*dev
, unsigned long addr
, int len
)
244 /* XXX Somebody please fill this in */
248 static const struct sparc32_dma_ops iounit_dma_ops
= {
249 .get_scsi_one
= iounit_get_scsi_one
,
250 .get_scsi_sgl
= iounit_get_scsi_sgl
,
251 .release_scsi_one
= iounit_release_scsi_one
,
252 .release_scsi_sgl
= iounit_release_scsi_sgl
,
254 .map_dma_area
= iounit_map_dma_area
,
255 .unmap_dma_area
= iounit_unmap_dma_area
,
259 void __init
ld_mmu_iounit(void)
261 sparc32_dma_ops
= &iounit_dma_ops
;