diff options
Diffstat (limited to 'firmware/target/arm/gigabeat/meg-fx/mmu-meg-fx.c')
-rw-r--r-- | firmware/target/arm/gigabeat/meg-fx/mmu-meg-fx.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/firmware/target/arm/gigabeat/meg-fx/mmu-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/mmu-meg-fx.c new file mode 100644 index 0000000000..05b206c8ea --- /dev/null +++ b/firmware/target/arm/gigabeat/meg-fx/mmu-meg-fx.c | |||
@@ -0,0 +1,84 @@ | |||
1 | #include <string.h> | ||
2 | #include "s3c2440.h" | ||
3 | |||
4 | void map_memory(void); | ||
5 | static void enable_mmu(void); | ||
6 | static void set_ttb(void); | ||
7 | static void set_page_tables(void); | ||
8 | static void map_section(unsigned int pa, unsigned int va, int mb, int cache_flags); | ||
9 | |||
10 | #define SECTION_ADDRESS_MASK (-1 << 20) | ||
11 | #define CACHE_ALL (1 << 3 | 1 << 2 ) | ||
12 | #define CACHE_NONE 0 | ||
13 | #define BUFFERED (1 << 2) | ||
14 | #define MB (1 << 20) | ||
15 | |||
16 | void map_memory(void) { | ||
17 | set_ttb(); | ||
18 | set_page_tables(); | ||
19 | enable_mmu(); | ||
20 | } | ||
21 | |||
22 | unsigned int* ttb_base; | ||
23 | const int ttb_size = 4096; | ||
24 | |||
25 | void set_ttb() { | ||
26 | int i; | ||
27 | int* ttbPtr; | ||
28 | int domain_access; | ||
29 | |||
30 | /* must be 16Kb (0x4000) aligned */ | ||
31 | ttb_base = (int*)0x31F00000; | ||
32 | for (i=0; i<ttb_size; i++,ttbPtr++) | ||
33 | ttbPtr = 0; | ||
34 | asm volatile("mcr p15, 0, %0, c2, c0, 0" : : "r" (ttb_base)); | ||
35 | |||
36 | /* set domain D0 to "client" permission access */ | ||
37 | |||
38 | domain_access = 3; | ||
39 | asm volatile("mcr p15, 0, %0, c3, c0, 0" : : "r" (domain_access)); | ||
40 | |||
41 | } | ||
42 | |||
43 | void set_page_tables() { | ||
44 | |||
45 | map_section(0, 0, 0x1000, CACHE_NONE); | ||
46 | |||
47 | map_section(0x30000000, 0, 32, CACHE_NONE); /* map RAM to 0 */ | ||
48 | |||
49 | map_section(0x30000000, 0, 30, CACHE_ALL); /* cache the first 30 MB or RAM */ | ||
50 | map_section(0x31E00000, 0x31E00000, 1, BUFFERED); /* enable buffered writing for the framebuffer */ | ||
51 | } | ||
52 | |||
53 | void map_section(unsigned int pa, unsigned int va, int mb, int cache_flags) { | ||
54 | unsigned int* ttbPtr; | ||
55 | int i; | ||
56 | int section_no; | ||
57 | |||
58 | section_no = va >> 20; /* sections are 1Mb size */ | ||
59 | ttbPtr = ttb_base + section_no; | ||
60 | pa &= SECTION_ADDRESS_MASK; /* align to 1Mb */ | ||
61 | for(i=0; i<mb; i++, pa += MB) { | ||
62 | *(ttbPtr + i) = | ||
63 | pa | | ||
64 | 1 << 10 | /* superuser - r/w, user - no access */ | ||
65 | 0 << 5 | /* domain 0th */ | ||
66 | 1 << 4 | /* should be "1" */ | ||
67 | cache_flags | | ||
68 | 1 << 1; /* Section signature */ | ||
69 | } | ||
70 | } | ||
71 | |||
72 | static void enable_mmu(void) { | ||
73 | asm volatile("mov r0, #0\n" | ||
74 | "mcr p15, 0, r0, c8, c7, 0\n" /* invalidate TLB */ | ||
75 | |||
76 | "mcr p15, 0, r0, c7, c7,0\n" /* invalidate both icache and dcache */ | ||
77 | |||
78 | "mrc p15, 0, r0, c1, c0, 0\n" | ||
79 | "orr r0, r0, #1<<0\n" /* enable mmu bit, icache and dcache */ | ||
80 | "orr r0, r0, #1<<2\n" /* enable dcache */ | ||
81 | "orr r0, r0, #1<<12\n" /* enable icache */ | ||
82 | "mcr p15, 0, r0, c1, c0, 0" : : : "r0"); | ||
83 | asm volatile("nop \n nop \n nop \n nop"); | ||
84 | } | ||