2 ** Proll (PROM replacement)
3 ** iommu.c: Functions for DVMA management.
4 ** Copyright 1999 Pete Zaitcev
5 ** This code is licensed under GNU General Public License.
8 #include "libopenbios/bindings.h"
9 #include "drivers/drivers.h"
11 #include "libopenbios/ofmem.h"
13 #ifdef CONFIG_DEBUG_IOMMU
14 #define DPRINTF(fmt, args...) \
15 do { printk(fmt , ##args); } while (0)
17 #define DPRINTF(fmt, args...)
24 struct iommu_regs
*regs
;
25 unsigned int *page_table
;
26 unsigned long plow
; /* Base bus address */
29 static struct iommu ciommu
;
32 iommu_invalidate(struct iommu_regs
*iregs
)
38 * XXX This is a problematic interface. We alloc _memory_ which is uncached.
39 * So if we ever reuse allocations somebody is going to get uncached pages.
40 * Returned address is always aligned by page.
41 * BTW, we were not going to give away anonymous storage, were we not?
44 dvma_alloc(int size
, unsigned int *pphys
)
49 unsigned int mva
, mpa
;
52 struct iommu
*t
= &ciommu
;
55 npages
= (size
+ (PAGE_SIZE
-1)) / PAGE_SIZE
;
56 ret
= ofmem_posix_memalign(&va
, npages
* PAGE_SIZE
, PAGE_SIZE
);
60 ba
= (unsigned int)mem_alloc(&cdvmem
, npages
* PAGE_SIZE
, PAGE_SIZE
);
64 pa
= (unsigned int)va2pa((unsigned long)va
);
67 * Change page attributes in MMU to uncached.
69 mva
= (unsigned int) va
;
70 mpa
= (unsigned int) pa
;
71 ofmem_arch_early_map_pages(mpa
, mva
, npages
* PAGE_SIZE
, ofmem_arch_io_translation_mode(mpa
));
74 * Map into IOMMU page table.
76 mpa
= (unsigned int) pa
;
77 iopte
= &t
->page_table
[(ba
- t
->plow
) / PAGE_SIZE
];
78 for (i
= 0; i
< npages
; i
++) {
79 *iopte
++ = MKIOPTE(mpa
);
90 * This looks like initialization of CPU MMU but
91 * the routine is higher in food chain.
93 static struct iommu_regs
*
94 iommu_init(struct iommu
*t
, uint64_t base
)
98 #ifdef CONFIG_DEBUG_IOMMU
99 unsigned int impl
, vers
;
102 struct iommu_regs
*regs
;
104 unsigned long vasize
;
106 regs
= (struct iommu_regs
*)ofmem_map_io(base
, IOMMU_REGS
);
108 DPRINTF("Cannot map IOMMU\n");
112 #ifdef CONFIG_DEBUG_IOMMU
113 impl
= (regs
->control
& IOMMU_CTRL_IMPL
) >> 28;
114 vers
= (regs
->control
& IOMMU_CTRL_VERS
) >> 24;
118 tmp
&= ~(IOMMU_CTRL_RNGE
);
120 tmp
|= (IOMMU_RNGE_32MB
| IOMMU_CTRL_ENAB
);
121 t
->plow
= 0xfe000000; /* End - 32 MB */
122 /* Size of VA region that we manage */
123 vasize
= 0x2000000; /* 32 MB */
126 iommu_invalidate(regs
);
128 /* Allocate IOMMU page table */
129 /* Tremendous alignment causes great waste... */
130 ptsize
= (vasize
/ PAGE_SIZE
) * sizeof(int);
131 ret
= ofmem_posix_memalign((void *)&ptab
, ptsize
, ptsize
);
133 DPRINTF("Cannot allocate IOMMU table [0x%x]\n", ptsize
);
136 t
->page_table
= ptab
;
138 /* flush_cache_all(); */
139 /** flush_tlb_all(); **/
140 tmp
= (unsigned int)va2pa((unsigned long)ptab
);
141 regs
->base
= tmp
>> 4;
142 iommu_invalidate(regs
);
144 DPRINTF("IOMMU: impl %d vers %d page table at 0x%p (pa 0x%x) of size %d bytes\n",
145 impl
, vers
, t
->page_table
, tmp
, ptsize
);
147 mem_init(&cdvmem
, (char*)t
->plow
, (char *)0xfffff000);
152 ob_init_iommu(uint64_t base
)
154 struct iommu_regs
*regs
;
156 regs
= iommu_init(&ciommu
, base
);
159 fword("find-device");
160 PUSH((unsigned long)regs
);
167 PUSH(base
& 0xffffffff);