1 | /* |
---|
2 | * ARM920 MMU functions |
---|
3 | */ |
---|
4 | |
---|
5 | /* |
---|
6 | * Copyright (c) 2004 by Cogent Computer Systems |
---|
7 | * Written by Jay Monkman <jtm@lopingdog.com> |
---|
8 | */ |
---|
9 | |
---|
10 | #include <libcpu/mmu.h> |
---|
11 | #include <libcpu/arm-cp15.h> |
---|
12 | |
---|
13 | typedef uint32_t mmu_lvl1_t; |
---|
14 | |
---|
15 | extern uint32_t _ttbl_base; |
---|
16 | |
---|
17 | static void mmu_set_map_inval(mmu_lvl1_t *base); |
---|
18 | |
---|
19 | #define MMU_CTRL_MMU_EN (1 << 0) |
---|
20 | #define MMU_CTRL_ALIGN_FAULT_EN (1 << 1) |
---|
21 | #define MMU_CTRL_D_CACHE_EN (1 << 2) |
---|
22 | #define MMU_CTRL_DEFAULT (0xf << 3) |
---|
23 | #define MMU_CTRL_LITTLE_ENDIAN (0 << 7) |
---|
24 | #define MMU_CTRL_BIG_ENDIAN (1 << 7) |
---|
25 | #define MMU_CTRL_SYS_PROT (1 << 8) |
---|
26 | #define MMU_CTRL_ROM_PROT (1 << 9) |
---|
27 | #define MMU_CTRL_I_CACHE_EN (1 << 12) |
---|
28 | #define MMU_CTRL_LOW_VECT (0 << 13) |
---|
29 | #define MMU_CTRL_HIGH_VECT (1 << 13) |
---|
30 | |
---|
31 | |
---|
32 | #define MMU_SET_LVL1_SECT(addr, ap, dom, ce, be) \ |
---|
33 | (((addr) & 0xfff00000) | \ |
---|
34 | (ap) | \ |
---|
35 | (dom) | \ |
---|
36 | ((ce) << 3) | \ |
---|
37 | ((be) << 2) | \ |
---|
38 | 0x12) |
---|
39 | |
---|
40 | #define MMU_SET_LVL1_INVAL (0x0) |
---|
41 | |
---|
42 | #define MMU_SECT_AP_ALL (0x3 << 10) |
---|
43 | |
---|
44 | void mmu_init(mmu_sect_map_t *map) |
---|
45 | { |
---|
46 | mmu_lvl1_t *lvl1_base; |
---|
47 | int i; |
---|
48 | |
---|
49 | /* flush the cache and TLB */ |
---|
50 | arm_cp15_cache_invalidate(); |
---|
51 | arm_cp15_tlb_invalidate(); |
---|
52 | |
---|
53 | /* set manage mode access for all domains */ |
---|
54 | arm_cp15_set_domain_access_control(0xffffffff); |
---|
55 | |
---|
56 | lvl1_base = (mmu_lvl1_t *)&_ttbl_base; |
---|
57 | |
---|
58 | /* set up the trans table */ |
---|
59 | mmu_set_map_inval(lvl1_base); |
---|
60 | arm_cp15_set_translation_table_base(lvl1_base); |
---|
61 | |
---|
62 | /* create a 1:1 mapping of the entire address space */ |
---|
63 | i = 0; |
---|
64 | while(map[i].size != 0) { |
---|
65 | int c = 0; /* to avoid uninitialized warnings */ |
---|
66 | int b = 0; /* to avoid uninitialized warnings */ |
---|
67 | int pbase; |
---|
68 | int vbase; |
---|
69 | int sects; |
---|
70 | |
---|
71 | switch (map[i].cache_flags) { |
---|
72 | case MMU_CACHE_NONE: |
---|
73 | c = 0; |
---|
74 | b = 0; |
---|
75 | break; |
---|
76 | case MMU_CACHE_BUFFERED: |
---|
77 | c = 0; |
---|
78 | b = 1; |
---|
79 | break; |
---|
80 | case MMU_CACHE_WTHROUGH: |
---|
81 | c = 1; |
---|
82 | b = 0; |
---|
83 | break; |
---|
84 | case MMU_CACHE_WBACK: |
---|
85 | c = 1; |
---|
86 | b = 1; |
---|
87 | break; |
---|
88 | } |
---|
89 | |
---|
90 | pbase = (map[i].paddr & 0xfff00000) >> 20; |
---|
91 | vbase = (map[i].vaddr & 0xfff00000) >> 20; |
---|
92 | sects = map[i].size; |
---|
93 | |
---|
94 | while (sects > 0) { |
---|
95 | lvl1_base[vbase] = MMU_SET_LVL1_SECT(pbase << 20, |
---|
96 | MMU_SECT_AP_ALL, |
---|
97 | 0, |
---|
98 | c, |
---|
99 | b); |
---|
100 | pbase++; |
---|
101 | vbase++; |
---|
102 | sects--; |
---|
103 | } |
---|
104 | i++; |
---|
105 | } |
---|
106 | |
---|
107 | /* flush the cache and TLB */ |
---|
108 | arm_cp15_cache_invalidate(); |
---|
109 | arm_cp15_tlb_invalidate(); |
---|
110 | |
---|
111 | /* I & D caches turned on */ |
---|
112 | arm_cp15_set_control(MMU_CTRL_DEFAULT | |
---|
113 | MMU_CTRL_D_CACHE_EN | |
---|
114 | MMU_CTRL_I_CACHE_EN | |
---|
115 | MMU_CTRL_ALIGN_FAULT_EN | |
---|
116 | MMU_CTRL_LITTLE_ENDIAN | |
---|
117 | MMU_CTRL_MMU_EN); |
---|
118 | |
---|
119 | return; |
---|
120 | } |
---|
121 | |
---|
122 | /* set all the level 1 entrys to be invalid descriptors */ |
---|
123 | static void mmu_set_map_inval(mmu_lvl1_t *base) |
---|
124 | { |
---|
125 | int i; |
---|
126 | for (i = 0; i < (0x4000 / 4); i++) { |
---|
127 | base[i] = MMU_SET_LVL1_INVAL; |
---|
128 | } |
---|
129 | } |
---|
130 | |
---|
131 | void mmu_set_cpu_async_mode(void) |
---|
132 | { |
---|
133 | uint32_t reg; |
---|
134 | reg = arm_cp15_get_control(); |
---|
135 | reg |= 0xc0000000; |
---|
136 | arm_cp15_set_control(reg); |
---|
137 | } |
---|