OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [sparc/] [mm/] [iommu.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * iommu.c:  IOMMU specific routines for memory management.
3
 *
4
 * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
5
 * Copyright (C) 1995,2002 Pete Zaitcev     (zaitcev@yahoo.com)
6
 * Copyright (C) 1996 Eddie C. Dost    (ecd@skynet.be)
7
 * Copyright (C) 1997,1998 Jakub Jelinek    (jj@sunsite.mff.cuni.cz)
8
 */
9
 
10
#include <linux/kernel.h>
11
#include <linux/init.h>
12
#include <linux/mm.h>
13
#include <linux/slab.h>
14
#include <linux/highmem.h>      /* pte_offset_map => kmap_atomic */
15
#include <linux/scatterlist.h>
16
 
17
#include <asm/pgalloc.h>
18
#include <asm/pgtable.h>
19
#include <asm/sbus.h>
20
#include <asm/io.h>
21
#include <asm/mxcc.h>
22
#include <asm/mbus.h>
23
#include <asm/cacheflush.h>
24
#include <asm/tlbflush.h>
25
#include <asm/bitext.h>
26
#include <asm/iommu.h>
27
#include <asm/dma.h>
28
 
29
/*
30
 * This can be sized dynamically, but we will do this
31
 * only when we have a guidance about actual I/O pressures.
32
 */
33
#define IOMMU_RNGE      IOMMU_RNGE_256MB
34
#define IOMMU_START     0xF0000000
35
#define IOMMU_WINSIZE   (256*1024*1024U)
36
#define IOMMU_NPTES     (IOMMU_WINSIZE/PAGE_SIZE)       /* 64K PTEs, 265KB */
37
#define IOMMU_ORDER     6                               /* 4096 * (1<<6) */
38
 
39
/* srmmu.c */
40
extern int viking_mxcc_present;
41
BTFIXUPDEF_CALL(void, flush_page_for_dma, unsigned long)
42
#define flush_page_for_dma(page) BTFIXUP_CALL(flush_page_for_dma)(page)
43
extern int flush_page_for_dma_global;
44
static int viking_flush;
45
/* viking.S */
46
extern void viking_flush_page(unsigned long page);
47
extern void viking_mxcc_flush_page(unsigned long page);
48
 
49
/*
50
 * Values precomputed according to CPU type.
51
 */
52
static unsigned int ioperm_noc;         /* Consistent mapping iopte flags */
53
static pgprot_t dvma_prot;              /* Consistent mapping pte flags */
54
 
55
#define IOPERM        (IOPTE_CACHE | IOPTE_WRITE | IOPTE_VALID)
56
#define MKIOPTE(pfn, perm) (((((pfn)<<8) & IOPTE_PAGE) | (perm)) & ~IOPTE_WAZ)
57
 
58
void __init
59
iommu_init(int iommund, struct sbus_bus *sbus)
60
{
61
        unsigned int impl, vers;
62
        unsigned long tmp;
63
        struct iommu_struct *iommu;
64
        struct linux_prom_registers iommu_promregs[PROMREG_MAX];
65
        struct resource r;
66
        unsigned long *bitmap;
67
 
68
        iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC);
69
        if (!iommu) {
70
                prom_printf("Unable to allocate iommu structure\n");
71
                prom_halt();
72
        }
73
        iommu->regs = NULL;
74
        if (prom_getproperty(iommund, "reg", (void *) iommu_promregs,
75
                         sizeof(iommu_promregs)) != -1) {
76
                memset(&r, 0, sizeof(r));
77
                r.flags = iommu_promregs[0].which_io;
78
                r.start = iommu_promregs[0].phys_addr;
79
                iommu->regs = (struct iommu_regs *)
80
                        sbus_ioremap(&r, 0, PAGE_SIZE * 3, "iommu_regs");
81
        }
82
        if (!iommu->regs) {
83
                prom_printf("Cannot map IOMMU registers\n");
84
                prom_halt();
85
        }
86
        impl = (iommu->regs->control & IOMMU_CTRL_IMPL) >> 28;
87
        vers = (iommu->regs->control & IOMMU_CTRL_VERS) >> 24;
88
        tmp = iommu->regs->control;
89
        tmp &= ~(IOMMU_CTRL_RNGE);
90
        tmp |= (IOMMU_RNGE_256MB | IOMMU_CTRL_ENAB);
91
        iommu->regs->control = tmp;
92
        iommu_invalidate(iommu->regs);
93
        iommu->start = IOMMU_START;
94
        iommu->end = 0xffffffff;
95
 
96
        /* Allocate IOMMU page table */
97
        /* Stupid alignment constraints give me a headache.
98
           We need 256K or 512K or 1M or 2M area aligned to
99
           its size and current gfp will fortunately give
100
           it to us. */
101
        tmp = __get_free_pages(GFP_KERNEL, IOMMU_ORDER);
102
        if (!tmp) {
103
                prom_printf("Unable to allocate iommu table [0x%08x]\n",
104
                            IOMMU_NPTES*sizeof(iopte_t));
105
                prom_halt();
106
        }
107
        iommu->page_table = (iopte_t *)tmp;
108
 
109
        /* Initialize new table. */
110
        memset(iommu->page_table, 0, IOMMU_NPTES*sizeof(iopte_t));
111
        flush_cache_all();
112
        flush_tlb_all();
113
        iommu->regs->base = __pa((unsigned long) iommu->page_table) >> 4;
114
        iommu_invalidate(iommu->regs);
115
 
116
        bitmap = kmalloc(IOMMU_NPTES>>3, GFP_KERNEL);
117
        if (!bitmap) {
118
                prom_printf("Unable to allocate iommu bitmap [%d]\n",
119
                            (int)(IOMMU_NPTES>>3));
120
                prom_halt();
121
        }
122
        bit_map_init(&iommu->usemap, bitmap, IOMMU_NPTES);
123
        /* To be coherent on HyperSparc, the page color of DVMA
124
         * and physical addresses must match.
125
         */
126
        if (srmmu_modtype == HyperSparc)
127
                iommu->usemap.num_colors = vac_cache_size >> PAGE_SHIFT;
128
        else
129
                iommu->usemap.num_colors = 1;
130
 
131
        printk("IOMMU: impl %d vers %d table 0x%p[%d B] map [%d b]\n",
132
            impl, vers, iommu->page_table,
133
            (int)(IOMMU_NPTES*sizeof(iopte_t)), (int)IOMMU_NPTES);
134
 
135
        sbus->ofdev.dev.archdata.iommu = iommu;
136
}
137
 
138
/* This begs to be btfixup-ed by srmmu. */
139
/* Flush the iotlb entries to ram. */
140
/* This could be better if we didn't have to flush whole pages. */
141
static void iommu_flush_iotlb(iopte_t *iopte, unsigned int niopte)
142
{
143
        unsigned long start;
144
        unsigned long end;
145
 
146
        start = (unsigned long)iopte;
147
        end = PAGE_ALIGN(start + niopte*sizeof(iopte_t));
148
        start &= PAGE_MASK;
149
        if (viking_mxcc_present) {
150
                while(start < end) {
151
                        viking_mxcc_flush_page(start);
152
                        start += PAGE_SIZE;
153
                }
154
        } else if (viking_flush) {
155
                while(start < end) {
156
                        viking_flush_page(start);
157
                        start += PAGE_SIZE;
158
                }
159
        } else {
160
                while(start < end) {
161
                        __flush_page_to_ram(start);
162
                        start += PAGE_SIZE;
163
                }
164
        }
165
}
166
 
167
static u32 iommu_get_one(struct page *page, int npages, struct sbus_bus *sbus)
168
{
169
        struct iommu_struct *iommu = sbus->ofdev.dev.archdata.iommu;
170
        int ioptex;
171
        iopte_t *iopte, *iopte0;
172
        unsigned int busa, busa0;
173
        int i;
174
 
175
        /* page color = pfn of page */
176
        ioptex = bit_map_string_get(&iommu->usemap, npages, page_to_pfn(page));
177
        if (ioptex < 0)
178
                panic("iommu out");
179
        busa0 = iommu->start + (ioptex << PAGE_SHIFT);
180
        iopte0 = &iommu->page_table[ioptex];
181
 
182
        busa = busa0;
183
        iopte = iopte0;
184
        for (i = 0; i < npages; i++) {
185
                iopte_val(*iopte) = MKIOPTE(page_to_pfn(page), IOPERM);
186
                iommu_invalidate_page(iommu->regs, busa);
187
                busa += PAGE_SIZE;
188
                iopte++;
189
                page++;
190
        }
191
 
192
        iommu_flush_iotlb(iopte0, npages);
193
 
194
        return busa0;
195
}
196
 
197
static u32 iommu_get_scsi_one(char *vaddr, unsigned int len,
198
    struct sbus_bus *sbus)
199
{
200
        unsigned long off;
201
        int npages;
202
        struct page *page;
203
        u32 busa;
204
 
205
        off = (unsigned long)vaddr & ~PAGE_MASK;
206
        npages = (off + len + PAGE_SIZE-1) >> PAGE_SHIFT;
207
        page = virt_to_page((unsigned long)vaddr & PAGE_MASK);
208
        busa = iommu_get_one(page, npages, sbus);
209
        return busa + off;
210
}
211
 
212
static __u32 iommu_get_scsi_one_noflush(char *vaddr, unsigned long len, struct sbus_bus *sbus)
213
{
214
        return iommu_get_scsi_one(vaddr, len, sbus);
215
}
216
 
217
static __u32 iommu_get_scsi_one_gflush(char *vaddr, unsigned long len, struct sbus_bus *sbus)
218
{
219
        flush_page_for_dma(0);
220
        return iommu_get_scsi_one(vaddr, len, sbus);
221
}
222
 
223
static __u32 iommu_get_scsi_one_pflush(char *vaddr, unsigned long len, struct sbus_bus *sbus)
224
{
225
        unsigned long page = ((unsigned long) vaddr) & PAGE_MASK;
226
 
227
        while(page < ((unsigned long)(vaddr + len))) {
228
                flush_page_for_dma(page);
229
                page += PAGE_SIZE;
230
        }
231
        return iommu_get_scsi_one(vaddr, len, sbus);
232
}
233
 
234
static void iommu_get_scsi_sgl_noflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
235
{
236
        int n;
237
 
238
        while (sz != 0) {
239
                --sz;
240
                n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT;
241
                sg->dvma_address = iommu_get_one(sg_page(sg), n, sbus) + sg->offset;
242
                sg->dvma_length = (__u32) sg->length;
243
                sg = sg_next(sg);
244
        }
245
}
246
 
247
static void iommu_get_scsi_sgl_gflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
248
{
249
        int n;
250
 
251
        flush_page_for_dma(0);
252
        while (sz != 0) {
253
                --sz;
254
                n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT;
255
                sg->dvma_address = iommu_get_one(sg_page(sg), n, sbus) + sg->offset;
256
                sg->dvma_length = (__u32) sg->length;
257
                sg = sg_next(sg);
258
        }
259
}
260
 
261
static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
262
{
263
        unsigned long page, oldpage = 0;
264
        int n, i;
265
 
266
        while(sz != 0) {
267
                --sz;
268
 
269
                n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT;
270
 
271
                /*
272
                 * We expect unmapped highmem pages to be not in the cache.
273
                 * XXX Is this a good assumption?
274
                 * XXX What if someone else unmaps it here and races us?
275
                 */
276
                if ((page = (unsigned long) page_address(sg_page(sg))) != 0) {
277
                        for (i = 0; i < n; i++) {
278
                                if (page != oldpage) {  /* Already flushed? */
279
                                        flush_page_for_dma(page);
280
                                        oldpage = page;
281
                                }
282
                                page += PAGE_SIZE;
283
                        }
284
                }
285
 
286
                sg->dvma_address = iommu_get_one(sg_page(sg), n, sbus) + sg->offset;
287
                sg->dvma_length = (__u32) sg->length;
288
                sg = sg_next(sg);
289
        }
290
}
291
 
292
static void iommu_release_one(u32 busa, int npages, struct sbus_bus *sbus)
293
{
294
        struct iommu_struct *iommu = sbus->ofdev.dev.archdata.iommu;
295
        int ioptex;
296
        int i;
297
 
298
        BUG_ON(busa < iommu->start);
299
        ioptex = (busa - iommu->start) >> PAGE_SHIFT;
300
        for (i = 0; i < npages; i++) {
301
                iopte_val(iommu->page_table[ioptex + i]) = 0;
302
                iommu_invalidate_page(iommu->regs, busa);
303
                busa += PAGE_SIZE;
304
        }
305
        bit_map_clear(&iommu->usemap, ioptex, npages);
306
}
307
 
308
static void iommu_release_scsi_one(__u32 vaddr, unsigned long len, struct sbus_bus *sbus)
309
{
310
        unsigned long off;
311
        int npages;
312
 
313
        off = vaddr & ~PAGE_MASK;
314
        npages = (off + len + PAGE_SIZE-1) >> PAGE_SHIFT;
315
        iommu_release_one(vaddr & PAGE_MASK, npages, sbus);
316
}
317
 
318
static void iommu_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
319
{
320
        int n;
321
 
322
        while(sz != 0) {
323
                --sz;
324
 
325
                n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT;
326
                iommu_release_one(sg->dvma_address & PAGE_MASK, n, sbus);
327
                sg->dvma_address = 0x21212121;
328
                sg = sg_next(sg);
329
        }
330
}
331
 
332
#ifdef CONFIG_SBUS
333
static int iommu_map_dma_area(dma_addr_t *pba, unsigned long va,
334
    unsigned long addr, int len)
335
{
336
        unsigned long page, end;
337
        struct iommu_struct *iommu = sbus_root->ofdev.dev.archdata.iommu;
338
        iopte_t *iopte = iommu->page_table;
339
        iopte_t *first;
340
        int ioptex;
341
 
342
        BUG_ON((va & ~PAGE_MASK) != 0);
343
        BUG_ON((addr & ~PAGE_MASK) != 0);
344
        BUG_ON((len & ~PAGE_MASK) != 0);
345
 
346
        /* page color = physical address */
347
        ioptex = bit_map_string_get(&iommu->usemap, len >> PAGE_SHIFT,
348
                addr >> PAGE_SHIFT);
349
        if (ioptex < 0)
350
                panic("iommu out");
351
 
352
        iopte += ioptex;
353
        first = iopte;
354
        end = addr + len;
355
        while(addr < end) {
356
                page = va;
357
                {
358
                        pgd_t *pgdp;
359
                        pmd_t *pmdp;
360
                        pte_t *ptep;
361
 
362
                        if (viking_mxcc_present)
363
                                viking_mxcc_flush_page(page);
364
                        else if (viking_flush)
365
                                viking_flush_page(page);
366
                        else
367
                                __flush_page_to_ram(page);
368
 
369
                        pgdp = pgd_offset(&init_mm, addr);
370
                        pmdp = pmd_offset(pgdp, addr);
371
                        ptep = pte_offset_map(pmdp, addr);
372
 
373
                        set_pte(ptep, mk_pte(virt_to_page(page), dvma_prot));
374
                }
375
                iopte_val(*iopte++) =
376
                    MKIOPTE(page_to_pfn(virt_to_page(page)), ioperm_noc);
377
                addr += PAGE_SIZE;
378
                va += PAGE_SIZE;
379
        }
380
        /* P3: why do we need this?
381
         *
382
         * DAVEM: Because there are several aspects, none of which
383
         *        are handled by a single interface.  Some cpus are
384
         *        completely not I/O DMA coherent, and some have
385
         *        virtually indexed caches.  The driver DMA flushing
386
         *        methods handle the former case, but here during
387
         *        IOMMU page table modifications, and usage of non-cacheable
388
         *        cpu mappings of pages potentially in the cpu caches, we have
389
         *        to handle the latter case as well.
390
         */
391
        flush_cache_all();
392
        iommu_flush_iotlb(first, len >> PAGE_SHIFT);
393
        flush_tlb_all();
394
        iommu_invalidate(iommu->regs);
395
 
396
        *pba = iommu->start + (ioptex << PAGE_SHIFT);
397
        return 0;
398
}
399
 
400
static void iommu_unmap_dma_area(unsigned long busa, int len)
401
{
402
        struct iommu_struct *iommu = sbus_root->ofdev.dev.archdata.iommu;
403
        iopte_t *iopte = iommu->page_table;
404
        unsigned long end;
405
        int ioptex = (busa - iommu->start) >> PAGE_SHIFT;
406
 
407
        BUG_ON((busa & ~PAGE_MASK) != 0);
408
        BUG_ON((len & ~PAGE_MASK) != 0);
409
 
410
        iopte += ioptex;
411
        end = busa + len;
412
        while (busa < end) {
413
                iopte_val(*iopte++) = 0;
414
                busa += PAGE_SIZE;
415
        }
416
        flush_tlb_all();
417
        iommu_invalidate(iommu->regs);
418
        bit_map_clear(&iommu->usemap, ioptex, len >> PAGE_SHIFT);
419
}
420
 
421
static struct page *iommu_translate_dvma(unsigned long busa)
422
{
423
        struct iommu_struct *iommu = sbus_root->ofdev.dev.archdata.iommu;
424
        iopte_t *iopte = iommu->page_table;
425
 
426
        iopte += ((busa - iommu->start) >> PAGE_SHIFT);
427
        return pfn_to_page((iopte_val(*iopte) & IOPTE_PAGE) >> (PAGE_SHIFT-4));
428
}
429
#endif
430
 
431
static char *iommu_lockarea(char *vaddr, unsigned long len)
432
{
433
        return vaddr;
434
}
435
 
436
static void iommu_unlockarea(char *vaddr, unsigned long len)
437
{
438
}
439
 
440
void __init ld_mmu_iommu(void)
441
{
442
        viking_flush = (BTFIXUPVAL_CALL(flush_page_for_dma) == (unsigned long)viking_flush_page);
443
        BTFIXUPSET_CALL(mmu_lockarea, iommu_lockarea, BTFIXUPCALL_RETO0);
444
        BTFIXUPSET_CALL(mmu_unlockarea, iommu_unlockarea, BTFIXUPCALL_NOP);
445
 
446
        if (!BTFIXUPVAL_CALL(flush_page_for_dma)) {
447
                /* IO coherent chip */
448
                BTFIXUPSET_CALL(mmu_get_scsi_one, iommu_get_scsi_one_noflush, BTFIXUPCALL_RETO0);
449
                BTFIXUPSET_CALL(mmu_get_scsi_sgl, iommu_get_scsi_sgl_noflush, BTFIXUPCALL_NORM);
450
        } else if (flush_page_for_dma_global) {
451
                /* flush_page_for_dma flushes everything, no matter of what page is it */
452
                BTFIXUPSET_CALL(mmu_get_scsi_one, iommu_get_scsi_one_gflush, BTFIXUPCALL_NORM);
453
                BTFIXUPSET_CALL(mmu_get_scsi_sgl, iommu_get_scsi_sgl_gflush, BTFIXUPCALL_NORM);
454
        } else {
455
                BTFIXUPSET_CALL(mmu_get_scsi_one, iommu_get_scsi_one_pflush, BTFIXUPCALL_NORM);
456
                BTFIXUPSET_CALL(mmu_get_scsi_sgl, iommu_get_scsi_sgl_pflush, BTFIXUPCALL_NORM);
457
        }
458
        BTFIXUPSET_CALL(mmu_release_scsi_one, iommu_release_scsi_one, BTFIXUPCALL_NORM);
459
        BTFIXUPSET_CALL(mmu_release_scsi_sgl, iommu_release_scsi_sgl, BTFIXUPCALL_NORM);
460
 
461
#ifdef CONFIG_SBUS
462
        BTFIXUPSET_CALL(mmu_map_dma_area, iommu_map_dma_area, BTFIXUPCALL_NORM);
463
        BTFIXUPSET_CALL(mmu_unmap_dma_area, iommu_unmap_dma_area, BTFIXUPCALL_NORM);
464
        BTFIXUPSET_CALL(mmu_translate_dvma, iommu_translate_dvma, BTFIXUPCALL_NORM);
465
#endif
466
 
467
        if (viking_mxcc_present || srmmu_modtype == HyperSparc) {
468
                dvma_prot = __pgprot(SRMMU_CACHE | SRMMU_ET_PTE | SRMMU_PRIV);
469
                ioperm_noc = IOPTE_CACHE | IOPTE_WRITE | IOPTE_VALID;
470
        } else {
471
                dvma_prot = __pgprot(SRMMU_ET_PTE | SRMMU_PRIV);
472
                ioperm_noc = IOPTE_WRITE | IOPTE_VALID;
473
        }
474
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.