summaryrefslogtreecommitdiff
path: root/firmware/target/mips/mmu-mips.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/mmu-mips.c')
-rw-r--r--firmware/target/mips/mmu-mips.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/firmware/target/mips/mmu-mips.c b/firmware/target/mips/mmu-mips.c
new file mode 100644
index 0000000000..3c1b932325
--- /dev/null
+++ b/firmware/target/mips/mmu-mips.c
@@ -0,0 +1,125 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 by Maurus Cuelenaere
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "mips.h"
24#include "mipsregs.h"
25#include "system.h"
26#include "mmu-mips.h"
27
28#define BARRIER \
29 __asm__ __volatile__( \
30 " .set noreorder \n" \
31 " nop \n" \
32 " nop \n" \
33 " nop \n" \
34 " nop \n" \
35 " nop \n" \
36 " nop \n" \
37 " .set reorder \n");
38
39#define DEFAULT_PAGE_SHIFT PL_4K
40#define DEFAULT_PAGE_MASK PM_4K
41#define UNIQUE_ENTRYHI(idx, ps) (A_K0BASE + ((idx) << (ps + 1)))
42#define ASID_MASK M_EntryHiASID
43#define VPN2_SHIFT S_EntryHiVPN2
44#define PFN_SHIFT S_EntryLoPFN
45#define PFN_MASK 0xffffff
46static void local_flush_tlb_all(void)
47{
48 unsigned long old_ctx;
49 int entry;
50 unsigned int old_irq = disable_irq_save();
51
52 /* Save old context and create impossible VPN2 value */
53 old_ctx = read_c0_entryhi();
54 write_c0_entrylo0(0);
55 write_c0_entrylo1(0);
56 BARRIER;
57
58 /* Blast 'em all away. */
59 for(entry = 0; entry < 32; entry++)
60 {
61 /* Make sure all entries differ. */
62 write_c0_entryhi(UNIQUE_ENTRYHI(entry, DEFAULT_PAGE_SHIFT));
63 write_c0_index(entry);
64 BARRIER;
65 tlb_write_indexed();
66 }
67 BARRIER;
68 write_c0_entryhi(old_ctx);
69
70 restore_irq(old_irq);
71}
72
73static void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
74 unsigned long entryhi, unsigned long pagemask)
75{
76 unsigned long wired;
77 unsigned long old_pagemask;
78 unsigned long old_ctx;
79 unsigned int old_irq = disable_irq_save();
80
81 old_ctx = read_c0_entryhi() & ASID_MASK;
82 old_pagemask = read_c0_pagemask();
83 wired = read_c0_wired();
84 write_c0_wired(wired + 1);
85 write_c0_index(wired);
86 BARRIER;
87 write_c0_pagemask(pagemask);
88 write_c0_entryhi(entryhi);
89 write_c0_entrylo0(entrylo0);
90 write_c0_entrylo1(entrylo1);
91 BARRIER;
92 tlb_write_indexed();
93 BARRIER;
94
95 write_c0_entryhi(old_ctx);
96 BARRIER;
97 write_c0_pagemask(old_pagemask);
98 local_flush_tlb_all();
99 restore_irq(old_irq);
100}
101
102void map_address(unsigned long virtual, unsigned long physical, unsigned long length)
103{
104 unsigned long entry0 = (physical & PFN_MASK) << PFN_SHIFT;
105 unsigned long entry1 = ((physical+length) & PFN_MASK) << PFN_SHIFT;
106 unsigned long entryhi = virtual & ~VPN2_SHIFT;
107
108 entry0 |= (M_EntryLoG | M_EntryLoV | (K_CacheAttrC << S_EntryLoC) );
109 entry1 |= (M_EntryLoG | M_EntryLoV | (K_CacheAttrC << S_EntryLoC) );
110
111 add_wired_entry(entry0, entry1, entryhi, DEFAULT_PAGE_MASK);
112}
113
114void tlb_init(void)
115{
116 write_c0_pagemask(DEFAULT_PAGE_MASK);
117 write_c0_wired(0);
118 write_c0_framemask(0);
119
120 local_flush_tlb_all();
121/*
122 map_address(0x80000000, 0x80000000, 0x4000);
123 map_address(0x80004000, 0x80004000, MEM * 0x100000);
124*/
125}