linux-bk/arch/mips/mm/rm7k.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * r4xx0.c: R4000 processor variant specific MMU/Cache routines.
   7 *
   8 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
   9 * Copyright (C) 1997, 1998 Ralf Baechle ralf@gnu.org
  10 *
  11 * To do:
  12 *
  13 *  - this code is a overbloated pig
  14 *  - many of the bug workarounds are not efficient at all, but at
  15 *    least they are functional ...
  16 */
  17#include <linux/init.h>
  18#include <linux/kernel.h>
  19#include <linux/sched.h>
  20#include <linux/mm.h>
  21
  22#include <asm/io.h>
  23#include <asm/page.h>
  24#include <asm/pgtable.h>
  25#include <asm/system.h>
  26#include <asm/bootinfo.h>
  27#include <asm/mmu_context.h>
  28
  29/* CP0 hazard avoidance. */
  30#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
  31                                     "nop; nop; nop; nop; nop; nop;\n\t" \
  32                                     ".set reorder\n\t")
  33
  34/* Primary cache parameters. */
  35static int icache_size, dcache_size; /* Size in bytes */
  36
  37#define ic_lsize        32              /* Fixed to 32 byte on RM7000  */
  38#define dc_lsize        32              /* Fixed to 32 byte on RM7000  */
  39#define sc_lsize        32              /* Fixed to 32 byte on RM7000  */
  40#define tc_pagesize     (32*128)
  41
  42/* Secondary cache parameters. */
  43#define scache_size     (256*1024)      /* Fixed to 256KiB on RM7000 */
  44
  45#include <asm/cacheops.h>
  46#include <asm/r4kcache.h>
  47
  48int rm7k_tcache_enabled = 0;
  49
  50/*
  51 * Not added to asm/r4kcache.h because it seems to be RM7000-specific.
  52 */
  53#define Page_Invalidate_T 0x16
  54
  55static inline void invalidate_tcache_page(unsigned long addr)
  56{
  57        __asm__ __volatile__(
  58                ".set\tnoreorder\t\t\t# invalidate_tcache_page\n\t"
  59                ".set\tmips3\n\t"
  60                "cache\t%1, (%0)\n\t"
  61                ".set\tmips0\n\t"
  62                ".set\treorder"
  63                :
  64                : "r" (addr),
  65                  "i" (Page_Invalidate_T));
  66}
  67
  68/*
  69 * Zero an entire page.  Note that while the RM7000 has a second level cache
  70 * it doesn't have a Create_Dirty_Excl_SD operation.
  71 */
  72static void rm7k_clear_page(void * page)
  73{
  74        __asm__ __volatile__(
  75                ".set\tnoreorder\n\t"
  76                ".set\tnoat\n\t"
  77                ".set\tmips3\n\t"
  78                "daddiu\t$1,%0,%2\n"
  79                "1:\tcache\t%3,(%0)\n\t"
  80                "sd\t$0,(%0)\n\t"
  81                "sd\t$0,8(%0)\n\t"
  82                "sd\t$0,16(%0)\n\t"
  83                "sd\t$0,24(%0)\n\t"
  84                "daddiu\t%0,64\n\t"
  85                "cache\t%3,-32(%0)\n\t"
  86                "sd\t$0,-32(%0)\n\t"
  87                "sd\t$0,-24(%0)\n\t"
  88                "sd\t$0,-16(%0)\n\t"
  89                "bne\t$1,%0,1b\n\t"
  90                "sd\t$0,-8(%0)\n\t"
  91                ".set\tmips0\n\t"
  92                ".set\tat\n\t"
  93                ".set\treorder"
  94                :"=r" (page)
  95                :"0" (page),
  96                 "I" (PAGE_SIZE),
  97                 "i" (Create_Dirty_Excl_D)
  98                :"$1","memory");
  99}
 100
 101
 102/*
 103 * Copy an entire page.  Note that while the RM7000 has a second level cache
 104 * it doesn't have a Create_Dirty_Excl_SD operation.
 105 */
 106static void rm7k_copy_page(void * to, void * from)
 107{
 108        unsigned long dummy1, dummy2;
 109        unsigned long reg1, reg2, reg3, reg4;
 110
 111        __asm__ __volatile__(
 112                ".set\tnoreorder\n\t"
 113                ".set\tnoat\n\t"
 114                ".set\tmips3\n\t"
 115                "daddiu\t$1,%0,%8\n"
 116                "1:\tcache\t%9,(%0)\n\t"
 117                "lw\t%2,(%1)\n\t"
 118                "lw\t%3,4(%1)\n\t"
 119                "lw\t%4,8(%1)\n\t"
 120                "lw\t%5,12(%1)\n\t"
 121                "sw\t%2,(%0)\n\t"
 122                "sw\t%3,4(%0)\n\t"
 123                "sw\t%4,8(%0)\n\t"
 124                "sw\t%5,12(%0)\n\t"
 125                "lw\t%2,16(%1)\n\t"
 126                "lw\t%3,20(%1)\n\t"
 127                "lw\t%4,24(%1)\n\t"
 128                "lw\t%5,28(%1)\n\t"
 129                "sw\t%2,16(%0)\n\t"
 130                "sw\t%3,20(%0)\n\t"
 131                "sw\t%4,24(%0)\n\t"
 132                "sw\t%5,28(%0)\n\t"
 133                "cache\t%9,32(%0)\n\t"
 134                "daddiu\t%0,64\n\t"
 135                "daddiu\t%1,64\n\t"
 136                "lw\t%2,-32(%1)\n\t"
 137                "lw\t%3,-28(%1)\n\t"
 138                "lw\t%4,-24(%1)\n\t"
 139                "lw\t%5,-20(%1)\n\t"
 140                "sw\t%2,-32(%0)\n\t"
 141                "sw\t%3,-28(%0)\n\t"
 142                "sw\t%4,-24(%0)\n\t"
 143                "sw\t%5,-20(%0)\n\t"
 144                "lw\t%2,-16(%1)\n\t"
 145                "lw\t%3,-12(%1)\n\t"
 146                "lw\t%4,-8(%1)\n\t"
 147                "lw\t%5,-4(%1)\n\t"
 148                "sw\t%2,-16(%0)\n\t"
 149                "sw\t%3,-12(%0)\n\t"
 150                "sw\t%4,-8(%0)\n\t"
 151                "bne\t$1,%0,1b\n\t"
 152                "sw\t%5,-4(%0)\n\t"
 153                ".set\tmips0\n\t"
 154                ".set\tat\n\t"
 155                ".set\treorder"
 156                :"=r" (dummy1), "=r" (dummy2),
 157                 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
 158                :"0" (to), "1" (from),
 159                 "I" (PAGE_SIZE),
 160                 "i" (Create_Dirty_Excl_D));
 161}
 162
 163static void __flush_cache_all_d32i32(void)
 164{
 165        blast_dcache32();
 166        blast_icache32();
 167}
 168
 169static inline void rm7k_flush_cache_all_d32i32(void)
 170{
 171        /* Yes! Caches that don't suck ...  */
 172}
 173
 174static void rm7k_flush_cache_range_d32i32(struct vm_area_struct *vma,
 175                                         unsigned long start,
 176                                         unsigned long end)
 177{
 178        /* RM7000 caches are sane ...  */
 179}
 180
 181static void rm7k_flush_cache_mm_d32i32(struct mm_struct *mm)
 182{
 183        /* RM7000 caches are sane ...  */
 184}
 185
 186static void rm7k_flush_cache_page_d32i32(struct vm_area_struct *vma,
 187                                        unsigned long page)
 188{
 189        /* RM7000 caches are sane ...  */
 190}
 191
 192static void rm7k_flush_page_to_ram_d32i32(struct page * page)
 193{
 194        /* Yes!  Caches that don't suck!  */
 195}
 196
 197static void rm7k_flush_icache_range(unsigned long start, unsigned long end)
 198{
 199        /*
 200         * FIXME: This is overdoing things and harms performance.
 201         */
 202        __flush_cache_all_d32i32();
 203}
 204
 205static void rm7k_flush_icache_page(struct vm_area_struct *vma,
 206                                   struct page *page)
 207{
 208        /*
 209         * FIXME: We should not flush the entire cache but establish some
 210         * temporary mapping and use hit_invalidate operation to flush out
 211         * the line from the cache.
 212         */
 213        __flush_cache_all_d32i32();
 214}
 215
 216
 217/*
 218 * Writeback and invalidate the primary cache dcache before DMA.
 219 * (XXX These need to be fixed ...)
 220 */
 221static void
 222rm7k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
 223{
 224        unsigned long end, a;
 225
 226        a = addr & ~(sc_lsize - 1);
 227        end = (addr + size) & ~(sc_lsize - 1);
 228        while (1) {
 229                flush_dcache_line(a);   /* Hit_Writeback_Inv_D */
 230                flush_icache_line(a);   /* Hit_Invalidate_I */
 231                flush_scache_line(a);   /* Hit_Writeback_Inv_SD */
 232                if (a == end) break;
 233                a += sc_lsize;
 234        }
 235
 236        if (!rm7k_tcache_enabled) 
 237                return;
 238
 239        a = addr & ~(tc_pagesize - 1);
 240        end = (addr + size) & ~(tc_pagesize - 1);
 241        while(1) {
 242                invalidate_tcache_page(a);      /* Page_Invalidate_T */
 243                if (a == end) break;
 244                a += tc_pagesize;
 245        }
 246}
 247               
 248static void
 249rm7k_dma_cache_inv(unsigned long addr, unsigned long size)
 250{
 251        unsigned long end, a;
 252
 253        a = addr & ~(sc_lsize - 1);
 254        end = (addr + size) & ~(sc_lsize - 1);
 255        while (1) {
 256                invalidate_dcache_line(a);      /* Hit_Invalidate_D */
 257                flush_icache_line(a);           /* Hit_Invalidate_I */
 258                invalidate_scache_line(a);      /* Hit_Invalidate_SD */
 259                if (a == end) break;
 260                a += sc_lsize;
 261        }
 262
 263        if (!rm7k_tcache_enabled) 
 264                return;
 265
 266        a = addr & ~(tc_pagesize - 1);
 267        end = (addr + size) & ~(tc_pagesize - 1);
 268        while(1) {
 269                invalidate_tcache_page(a);      /* Page_Invalidate_T */
 270                if (a == end) break;
 271                a += tc_pagesize;
 272        }
 273}
 274
 275static void
 276rm7k_dma_cache_wback(unsigned long addr, unsigned long size)
 277{
 278        panic("rm7k_dma_cache_wback called - should not happen.\n");
 279}
 280
 281/*
 282 * While we're protected against bad userland addresses we don't care
 283 * very much about what happens in that case.  Usually a segmentation
 284 * fault will dump the process later on anyway ...
 285 */
 286static void rm7k_flush_cache_sigtramp(unsigned long addr)
 287{
 288        protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
 289        protected_flush_icache_line(addr & ~(ic_lsize - 1));
 290}
 291
 292/*
 293 * Undocumented RM7000:  Bit 29 in the info register of the RM7000 v2.0
 294 * indicates if the TLB has 48 or 64 entries.
 295 *
 296 * 29      1 =>    64 entry JTLB
 297 *         0 =>    48 entry JTLB
 298 */
 299static inline int __attribute__((const)) ntlb_entries(void)
 300{
 301        if (get_info() & (1 << 29))
 302                return 64;
 303
 304        return 48;
 305}
 306
 307void flush_tlb_all(void)
 308{
 309        unsigned long flags;
 310        unsigned long old_ctx;
 311        int entry;
 312
 313        local_irq_save(flags);
 314        /* Save old context and create impossible VPN2 value */
 315        old_ctx = get_entryhi() & 0xff;
 316        set_entryhi(KSEG0);
 317        set_entrylo0(0);
 318        set_entrylo1(0);
 319        BARRIER;
 320
 321        entry = get_wired();
 322
 323        /* Blast 'em all away. */
 324        while (entry < ntlb_entries()) {
 325                set_index(entry);
 326                BARRIER;
 327                tlb_write_indexed();
 328                BARRIER;
 329                entry++;
 330        }
 331        BARRIER;
 332        set_entryhi(old_ctx);
 333        local_irq_restore(flags);
 334}
 335
 336void flush_tlb_mm(struct mm_struct *mm)
 337{
 338        if(mm->context != 0) {
 339                unsigned long flags;
 340
 341                local_irq_save(flags);
 342                get_new_mmu_context(mm, asid_cache);
 343                if (mm == current->mm)
 344                        set_entryhi(mm->context & 0xff);
 345                local_irq_restore(flags);
 346        }
 347}
 348
 349void flush_tlb_range(struct mm_struct *mm, unsigned long start,
 350                                unsigned long end)
 351{
 352        if(mm->context != 0) {
 353                unsigned long flags;
 354                int size;
 355
 356                local_irq_save(flags);
 357                size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
 358                size = (size + 1) >> 1;
 359                if (size <= (ntlb_entries() / 2)) {
 360                        int oldpid = (get_entryhi() & 0xff);
 361                        int newpid = (mm->context & 0xff);
 362
 363                        start &= (PAGE_MASK << 1);
 364                        end += ((PAGE_SIZE << 1) - 1);
 365                        end &= (PAGE_MASK << 1);
 366                        while(start < end) {
 367                                int idx;
 368
 369                                set_entryhi(start | newpid);
 370                                start += (PAGE_SIZE << 1);
 371                                BARRIER;
 372                                tlb_probe();
 373                                BARRIER;
 374                                idx = get_index();
 375                                set_entrylo0(0);
 376                                set_entrylo1(0);
 377                                set_entryhi(KSEG0);
 378                                BARRIER;
 379                                if(idx < 0)
 380                                        continue;
 381                                tlb_write_indexed();
 382                                BARRIER;
 383                        }
 384                        set_entryhi(oldpid);
 385                } else {
 386                        get_new_mmu_context(mm, asid_cache);
 387                        if(mm == current->mm)
 388                                set_entryhi(mm->context & 0xff);
 389                }
 390                local_irq_restore(flags);
 391        }
 392}
 393
 394void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 395{
 396        if(vma->vm_mm->context != 0) {
 397                unsigned long flags;
 398                int oldpid, newpid, idx;
 399
 400                newpid = (vma->vm_mm->context & 0xff);
 401                page &= (PAGE_MASK << 1);
 402                local_irq_save(flags);
 403                oldpid = (get_entryhi() & 0xff);
 404                set_entryhi(page | newpid);
 405                BARRIER;
 406                tlb_probe();
 407                BARRIER;
 408                idx = get_index();
 409                set_entrylo0(0);
 410                set_entrylo1(0);
 411                set_entryhi(KSEG0);
 412                if(idx < 0)
 413                        goto finish;
 414                BARRIER;
 415                tlb_write_indexed();
 416
 417        finish:
 418                BARRIER;
 419                set_entryhi(oldpid);
 420                local_irq_restore(flags);
 421        }
 422}
 423
 424void pgd_init(unsigned long page)
 425{
 426        unsigned long *p = (unsigned long *) page;
 427        int i;
 428
 429        for (i = 0; i < USER_PTRS_PER_PGD; i+=8) {
 430                p[i + 0] = (unsigned long) invalid_pte_table;
 431                p[i + 1] = (unsigned long) invalid_pte_table;
 432                p[i + 2] = (unsigned long) invalid_pte_table;
 433                p[i + 3] = (unsigned long) invalid_pte_table;
 434                p[i + 4] = (unsigned long) invalid_pte_table;
 435                p[i + 5] = (unsigned long) invalid_pte_table;
 436                p[i + 6] = (unsigned long) invalid_pte_table;
 437                p[i + 7] = (unsigned long) invalid_pte_table;
 438        }
 439}
 440
 441/*
 442 * We will need multiple versions of update_mmu_cache(), one that just
 443 * updates the TLB with the new pte(s), and another which also checks
 444 * for the R4k "end of page" hardware bug and does the needy.
 445 */
 446void update_mmu_cache(struct vm_area_struct * vma,
 447                                 unsigned long address, pte_t pte)
 448{
 449        unsigned long flags;
 450        pgd_t *pgdp;
 451        pmd_t *pmdp;
 452        pte_t *ptep;
 453        int idx, pid;
 454
 455        /*
 456         * Handle debugger faulting in for debugee.
 457         */
 458        if (current->active_mm != vma->vm_mm)
 459                return;
 460
 461        pid = get_entryhi() & 0xff;
 462
 463        local_irq_save(flags);
 464        address &= (PAGE_MASK << 1);
 465        set_entryhi(address | (pid));
 466        pgdp = pgd_offset(vma->vm_mm, address);
 467        BARRIER;
 468        tlb_probe();
 469        BARRIER;
 470        pmdp = pmd_offset(pgdp, address);
 471        idx = get_index();
 472        ptep = pte_offset(pmdp, address);
 473        BARRIER;
 474        set_entrylo0(pte_val(*ptep++) >> 6);
 475        set_entrylo1(pte_val(*ptep) >> 6);
 476        set_entryhi(address | (pid));
 477        BARRIER;
 478        if (idx < 0) {
 479                tlb_write_random();
 480        } else {
 481                tlb_write_indexed();
 482        }
 483        BARRIER;
 484        set_entryhi(pid);
 485        BARRIER;
 486        local_irq_restore(flags);
 487}
 488
 489void show_regs(struct pt_regs * regs)
 490{
 491        /* Saved main processor registers. */
 492        printk(KERN_INFO "$0 : %08lx %08lx %08lx %08lx\n",
 493               0UL, regs->regs[1], regs->regs[2], regs->regs[3]);
 494        printk(KERN_INFO "$4 : %08lx %08lx %08lx %08lx\n",
 495               regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
 496        printk(KERN_INFO "$8 : %08lx %08lx %08lx %08lx\n",
 497               regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]);
 498        printk(KERN_INFO "$12: %08lx %08lx %08lx %08lx\n",
 499               regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]);
 500        printk(KERN_INFO "$16: %08lx %08lx %08lx %08lx\n",
 501               regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]);
 502        printk(KERN_INFO "$20: %08lx %08lx %08lx %08lx\n",
 503               regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]);
 504        printk(KERN_INFO "$24: %08lx %08lx\n",
 505               regs->regs[24], regs->regs[25]);
 506        printk(KERN_INFO "$28: %08lx %08lx %08lx %08lx\n",
 507               regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]);
 508
 509        /* Saved cp0 registers. */
 510        printk(KERN_INFO "epc   : %08lx    %s\nStatus: %08lx\nCause : %08lx\n",
 511               regs->cp0_epc, print_tainted(), regs->cp0_status, regs->cp0_cause);
 512}
 513
 514void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
 515                     unsigned long entryhi, unsigned long pagemask)
 516{
 517        unsigned long flags;
 518        unsigned long wired;
 519        unsigned long old_pagemask;
 520        unsigned long old_ctx;
 521
 522        local_irq_save(flags);
 523        /* Save old context and create impossible VPN2 value */
 524        old_ctx = (get_entryhi() & 0xff);
 525        old_pagemask = get_pagemask();
 526        wired = get_wired();
 527        set_wired (wired + 1);
 528        set_index (wired);
 529        BARRIER;    
 530        set_pagemask (pagemask);
 531        set_entryhi(entryhi);
 532        set_entrylo0(entrylo0);
 533        set_entrylo1(entrylo1);
 534        BARRIER;    
 535        tlb_write_indexed();
 536        BARRIER;    
 537    
 538        set_entryhi(old_ctx);
 539        BARRIER;    
 540        set_pagemask (old_pagemask);
 541        flush_tlb_all();    
 542        local_irq_restore(flags);
 543}
 544
 545/* Used for loading TLB entries before trap_init() has started, when we
 546   don't actually want to add a wired entry which remains throughout the
 547   lifetime of the system */
 548
 549static int temp_tlb_entry __initdata;
 550
 551__init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
 552                               unsigned long entryhi, unsigned long pagemask)
 553{
 554        int ret = 0;
 555        unsigned long flags;
 556        unsigned long wired;
 557        unsigned long old_pagemask;
 558        unsigned long old_ctx;
 559
 560        local_irq_save(flags);
 561        /* Save old context and create impossible VPN2 value */
 562        old_ctx = (get_entryhi() & 0xff);
 563        old_pagemask = get_pagemask();
 564        wired = get_wired();
 565        if (--temp_tlb_entry < wired) {
 566                printk(KERN_WARNING "No TLB space left for add_temporary_entry\n");
 567                ret = -ENOSPC;
 568                goto out;
 569        }
 570
 571        set_index (temp_tlb_entry);
 572        BARRIER;    
 573        set_pagemask (pagemask);
 574        set_entryhi(entryhi);
 575        set_entrylo0(entrylo0);
 576        set_entrylo1(entrylo1);
 577        BARRIER;    
 578        tlb_write_indexed();
 579        BARRIER;    
 580    
 581        set_entryhi(old_ctx);
 582        BARRIER;    
 583        set_pagemask (old_pagemask);
 584 out:
 585        local_irq_restore(flags);
 586        return ret;
 587}
 588
 589
 590
 591/* Detect and size the caches. */
 592static inline void probe_icache(unsigned long config)
 593{
 594        icache_size = 1 << (12 + ((config >> 9) & 7));
 595
 596        printk(KERN_INFO "Primary instruction cache %dKiB.\n", icache_size >> 10);
 597}
 598
 599static inline void probe_dcache(unsigned long config)
 600{
 601        dcache_size = 1 << (12 + ((config >> 6) & 7));
 602
 603        printk(KERN_INFO "Primary data cache %dKiB.\n", dcache_size >> 10);
 604}
 605
 606
 607/* 
 608 * This function is executed in the uncached segment KSEG1.
 609 * It must not touch the stack, because the stack pointer still points
 610 * into KSEG0. 
 611 *
 612 * Three options:
 613 *      - Write it in assembly and guarantee that we don't use the stack.
 614 *      - Disable caching for KSEG0 before calling it.
 615 *      - Pray that GCC doesn't randomly start using the stack.
 616 *
 617 * This being Linux, we obviously take the least sane of those options -
 618 * following DaveM's lead in r4xx0.c
 619 *
 620 * It seems we get our kicks from relying on unguaranteed behaviour in GCC
 621 */
 622static __init void setup_scache(void)
 623{
 624        int register i;
 625        
 626        set_cp0_config(1<<3 /* CONF_SE */);
 627
 628        set_taglo(0);
 629        set_taghi(0);
 630        
 631        for (i=0; i<scache_size; i+=sc_lsize) {
 632                __asm__ __volatile__ (
 633                      ".set noreorder\n\t"
 634                      ".set mips3\n\t"
 635                      "cache %1, (%0)\n\t"
 636                      ".set mips0\n\t"
 637                      ".set reorder"
 638                      :
 639                      : "r" (KSEG0ADDR(i)),
 640                        "i" (Index_Store_Tag_SD));
 641        }
 642
 643}
 644
 645static inline void probe_scache(unsigned long config)
 646{
 647        void (*func)(void) = KSEG1ADDR(&setup_scache);
 648
 649        if ((config >> 31) & 1)
 650                return;
 651
 652        printk(KERN_INFO "Secondary cache %dKiB, linesize %d bytes.\n",
 653               (scache_size >> 10), sc_lsize);
 654
 655        if ((config >> 3) & 1)
 656                return;
 657
 658        printk(KERN_INFO "Enabling secondary cache...");
 659        func();
 660        printk("Done\n");
 661}
 662 
 663static inline void probe_tcache(unsigned long config)
 664{
 665        if ((config >> 17) & 1)
 666                return;
 667
 668        /* We can't enable the L3 cache yet. There may be board-specific
 669         * magic necessary to turn it on, and blindly asking the CPU to
 670         * start using it would may give cache errors.
 671         *
 672         * Also, board-specific knowledge may allow us to use the 
 673         * CACHE Flash_Invalidate_T instruction if the tag RAM supports
 674         * it, and may specify the size of the L3 cache so we don't have
 675         * to probe it. 
 676         */
 677        printk(KERN_INFO "Tertiary cache present, %s enabled\n",
 678               config&(1<<12) ? "already" : "not (yet)");
 679
 680        if ((config >> 12) & 1)
 681                rm7k_tcache_enabled = 1;
 682}
 683
 684void __init ld_mmu_rm7k(void)
 685{
 686        unsigned long config = read_32bit_cp0_register(CP0_CONFIG);
 687        unsigned long addr;
 688
 689        printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID));
 690
 691        change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
 692
 693        /* RM7000 erratum #31. The icache is screwed at startup. */
 694        set_taglo(0);
 695        set_taghi(0);
 696        for (addr = KSEG0; addr <= KSEG0 + 4096; addr += ic_lsize) {
 697                __asm__ __volatile__ (
 698                        ".set noreorder\n\t"
 699                        ".set mips3\n\t"
 700                        "cache\t%1, 0(%0)\n\t"
 701                        "cache\t%1, 0x1000(%0)\n\t"
 702                        "cache\t%1, 0x2000(%0)\n\t"
 703                        "cache\t%1, 0x3000(%0)\n\t"
 704                        "cache\t%2, 0(%0)\n\t"
 705                        "cache\t%2, 0x1000(%0)\n\t"
 706                        "cache\t%2, 0x2000(%0)\n\t"
 707                        "cache\t%2, 0x3000(%0)\n\t"
 708                        "cache\t%1, 0(%0)\n\t"
 709                        "cache\t%1, 0x1000(%0)\n\t"
 710                        "cache\t%1, 0x2000(%0)\n\t"
 711                        "cache\t%1, 0x3000(%0)\n\t"
 712                        ".set\tmips0\n\t"
 713                        ".set\treorder\n\t"
 714                        :
 715                        : "r" (addr), "i" (Index_Store_Tag_I), "i" (Fill));
 716        }
 717
 718#ifndef CONFIG_MIPS_UNCACHED
 719        change_cp0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_NONCOHERENT);
 720#endif
 721
 722        probe_icache(config);
 723        probe_dcache(config);
 724        probe_scache(config);
 725        probe_tcache(config);
 726
 727        printk("TLB has %d entries.\n", ntlb_entries());
 728
 729        _clear_page = rm7k_clear_page;
 730        _copy_page = rm7k_copy_page;
 731
 732        _flush_cache_all = rm7k_flush_cache_all_d32i32;
 733        ___flush_cache_all = __flush_cache_all_d32i32;
 734        _flush_cache_mm = rm7k_flush_cache_mm_d32i32;
 735        _flush_cache_range = rm7k_flush_cache_range_d32i32;
 736        _flush_cache_page = rm7k_flush_cache_page_d32i32;
 737        _flush_page_to_ram = rm7k_flush_page_to_ram_d32i32;
 738        _flush_cache_sigtramp = rm7k_flush_cache_sigtramp;
 739        _flush_icache_range = rm7k_flush_icache_range;
 740        _flush_icache_page = rm7k_flush_icache_page;
 741
 742        _dma_cache_wback_inv = rm7k_dma_cache_wback_inv;
 743        _dma_cache_wback = rm7k_dma_cache_wback;
 744        _dma_cache_inv = rm7k_dma_cache_inv;
 745
 746        __flush_cache_all_d32i32();
 747        write_32bit_cp0_register(CP0_WIRED, 0);
 748        temp_tlb_entry = ntlb_entries() - 1;
 749        write_32bit_cp0_register(CP0_PAGEMASK, PM_4K);
 750        flush_tlb_all();
 751}
 752
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.