1 @ vim:filetype=armasm:
\r
3 @ ARM940 initialization.
\r
4 @ Based on ogg940 code by Dzz.
\r
5 @ (c) Copyright 2007, Grazvydas "notaz" Ignotas
\r
7 .equ mmsp2_regs, (0xc0000000-0x02000000) @ assume we live @ 0x2000000 bank
\r
8 .equ shared_ctl, 0x00200000 @ this is where shared_ctl struncture is located
\r
15 b .b_undef @ undefined instructions
\r
16 b .b_swi @ software interrupt
\r
17 b .b_pabort @ prefetch abort
\r
18 b .b_dabort @ data abort
\r
19 b .b_reserved @ reserved
\r
43 mov sp, #0x100000 @ reset stack
\r
45 mov r0, #shared_ctl @ remember where we were when interrupt happened
\r
48 mov r0, #shared_ctl @ increment exception counter (for debug)
\r
56 @ we should never get here
\r
65 mov sp, #0x100000 @ set the stack top (1M)
\r
66 sub sp, sp, #4 @ minus 4
\r
68 @ set up memory region 0 -- the whole 4GB address space
\r
69 mov r0, #(0x1f<<1)|1 @ region data
\r
70 mcr p15, 0, r0, c6, c0, 0 @ opcode2 ~ data/instr
\r
71 mcr p15, 0, r0, c6, c0, 1
\r
73 @ set up region 1 which is the first 2 megabytes.
\r
74 mov r0, #(0x14<<1)|1 @ region data
\r
75 mcr p15, 0, r0, c6, c1, 0
\r
76 mcr p15, 0, r0, c6, c1, 1
\r
78 @ set up region 2: 64k 0x200000-0x210000
\r
79 mov r0, #(0x0f<<1)|1
\r
80 orr r0, r0, #0x200000
\r
81 mcr p15, 0, r0, c6, c2, 0
\r
82 mcr p15, 0, r0, c6, c2, 1
\r
84 @ set up region 3: 64k 0xbe000000-0xbe010000 (hw control registers)
\r
85 mov r0, #(0x0f<<1)|1
\r
86 orr r0, r0, #mmsp2_regs
\r
87 mcr p15, 0, r0, c6, c3, 0
\r
88 mcr p15, 0, r0, c6, c3, 1
\r
90 @ region 4: 4K 0x00000000-0x00001000 (boot code protection region)
\r
91 mov r0, #(0x0b<<1)|1
\r
92 mcr p15, 0, r0, c6, c4, 0
\r
93 mcr p15, 0, r0, c6, c4, 1
\r
95 @ region 5: 4M 0x00400000-0x00800000 (mp3 area part1)
\r
96 mov r0, #(0x15<<1)|1
\r
97 orr r0, r0, #0x00400000
\r
98 mcr p15, 0, r0, c6, c5, 0
\r
99 mcr p15, 0, r0, c6, c5, 1
\r
101 @ region 6: 8M 0x00800000-0x01000000 (mp3 area part2)
\r
102 mov r0, #(0x16<<1)|1
\r
103 orr r0, r0, #0x00800000
\r
104 mcr p15, 0, r0, c6, c6, 0
\r
105 mcr p15, 0, r0, c6, c6, 1
\r
107 @ set regions 1, 4, 5 and 6 to be cacheable (so the first 2M and mp3 area will be cacheable)
\r
108 mov r0, #(1<<1)|(1<<4)|(1<<5)|(1<<6)
\r
109 mcr p15, 0, r0, c2, c0, 0
\r
110 mcr p15, 0, r0, c2, c0, 1
\r
112 @ set region 1 to be bufferable too (only data)
\r
114 mcr p15, 0, r0, c3, c0, 0
\r
116 @ set access protection
\r
117 @ data: [full, full, no, full, full, full, no access] for regions [6 5 4 3 2 1 0]
\r
118 mov r0, # (3<<12)|(3<<10)|(0<<8)
\r
119 orr r0, r0, #(3<<6)|(3<< 4)|(3<< 2)|(0<<0)
\r
120 mcr p15, 0, r0, c5, c0, 0
\r
121 @ instructions: [no, no, full, no, no, full, no]
\r
122 mov r0, # (0<<12)|(0<<10)|(3<<8)
\r
123 orr r0, r0, #(0<<6)|(0<< 4)|(3<< 2)|(0<<0)
\r
124 mcr p15, 0, r0, c5, c0, 1
\r
126 mrc p15, 0, r0, c1, c0, 0 @ fetch current control reg
\r
127 orr r0, r0, #1 @ 0x00000001: enable protection unit
\r
128 orr r0, r0, #4 @ 0x00000004: enable D cache
\r
129 orr r0, r0, #0x1000 @ 0x00001000: enable I cache
\r
130 @ bic r0, r0, #0xC0000000
\r
131 @ orr r0, r0, #0x40000000 @ 0x40000000: synchronous, faster?
\r
132 orr r0, r0, #0xC0000000 @ 0xC0000000: async
\r
133 mcr p15, 0, r0, c1, c0, 0 @ set control reg
\r
135 @ flush (invalidate) the cache (just in case)
\r
137 mcr p15, 0, r0, c7, c6, 0
\r
139 @ remember which exception vector we came from (increment counter for debug)
\r
140 mov r0, #shared_ctl
\r
141 add r0, r0, r12, lsl #2
\r
146 @ remember last lr (for debug)
\r
147 mov r0, #shared_ctl
\r
151 @ ready to take first job-interrupt
\r
155 msr cpsr_c, r0 @ enable interrupts
\r
158 mcr p15, 0, r0, c7, c0, 4 @ wait for IRQ
\r
159 @ mcr p15, 0, r0, c15, c8, 2
\r
167 .global wait_get_job @ int oldjob
\r
170 mov r3, #mmsp2_regs
\r
171 orr r2, r3, #0x3B00
\r
172 orr r2, r2, #0x0046 @ DUALPEND940 register
\r
180 strh r1, [r2] @ clear finished job's pending bit
\r
189 movs r12,r12,lsr #1
\r
195 orr r2, r3, #0x4500
\r
196 str r0, [r2] @ clear all pending interrupts in irq controller's SRCPND register
\r
197 orr r2, r2, #0x0010
\r
198 str r0, [r2] @ clear all pending interrupts in irq controller's INTPND register
\r
206 @ some asm utils are also defined here:
\r
207 .global spend_cycles @ c
\r
210 mov r0, r0, lsr #2 @ 4 cycles/iteration
\r
211 sub r0, r0, #2 @ entry/exit/init
\r
219 @ clean-flush function from ARM940T technical reference manual
\r
220 .global dcache_clean_flush
\r
222 dcache_clean_flush:
\r
223 mov r1, #0 @ init line counter
\r
225 mov r0, #0 @ segment counter
\r
227 orr r2, r1, r0 @ make segment and line address
\r
228 mcr p15, 0, r2, c7, c14, 2 @ clean and flush that line
\r
229 add r0, r0, #0x10 @ incremet segment counter
\r
230 cmp r0, #0x40 @ complete all 4 segments?
\r
232 add r1, r1, #0x04000000 @ increment line counter
\r
233 cmp r1, #0 @ complete all lines?
\r
239 @ clean-only version
\r
240 .global dcache_clean
\r
243 mov r1, #0 @ init line counter
\r
245 mov r0, #0 @ segment counter
\r
247 orr r2, r1, r0 @ make segment and line address
\r
248 mcr p15, 0, r2, c7, c10, 2 @ clean that line
\r
249 add r0, r0, #0x10 @ incremet segment counter
\r
250 cmp r0, #0x40 @ complete all 4 segments?
\r
252 add r1, r1, #0x04000000 @ increment line counter
\r
253 cmp r1, #0 @ complete all lines?
\r
258 @ drain write buffer
\r
263 mcr p15, 0, r0, c7, c10, 4
\r
267 .global set_if_not_changed @ int *val, int oldval, int newval
\r
269 set_if_not_changed:
\r
273 strne r3, [r0] @ restore value which was changed there by other core
\r
278 @ pad the protected region.
\r