xref: /netbsd-src/sys/arch/epoc32/epoc32/epoc32_start.S (revision d7b7d02e733839920043e74f8c8422b1708f098c)
1/*	$NetBSD: epoc32_start.S,v 1.1 2013/04/28 12:11:26 kiyohara Exp $	*/
2/*
3 * Copyright (c) 2012, 2013 KIYOHARA Takashi
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <machine/asm.h>
29#include <machine/bootinfo.h>
30#include <arm/armreg.h>
31#include "assym.h"
32
33/*
34 * Kernel start routine for EPOC32
35 * this code is excuted at the very first after the kernel is loaded.
36 */
37	.text
38
39	.global _C_LABEL(epoc32_start)
40_C_LABEL(epoc32_start):
41
42	/* copy bootinfo */
43	adr	r1, bootinfo
44	mov	r2, #BTINFO_MAX_SIZE
45	sub	r2, r2, #4
460:
47	ldr	r3, [r0, r2]
48	str	r3, [r1, r2]
49	subs	r2, r2, #4
50	bge	0b
51
52	/*
53	 * Build page table from scratch.
54	 * Our boot-loader(e32boot) disables D-cache already.
55	 */
56	adr	r0, mmu_init_table
57	b	2f
58
591:
60	str	r3, [r2]
61	add	r2, r2, #4
62	add	r3, r3, #L1_S_SIZE
63	adds	r1, r1, #-1
64	bhi	1b
652:
66	ldmia	r0!, {r1, r2}		/* # of sections, VA */
67	ldr	r3, startup_pagetable	/* pagetable */
68	add	r2, r2, r3
69	ldr	r3, [r0], #4		/* # of PA|attr */
70	cmp	r1, #0
71	bne	1b
72
73	/*
74	 * Check physical memory segments. We require least 4MB for startup.
75	 */
76	adr	r0, bootinfo
77next_btinfo:
78	ldmia	r0, {r1, r2}
79	cmp	r2, #BTINFO_NONE
80	beq	99f			/* XXXX: Oops. no memory info? */
81	cmp	r2, #BTINFO_MEMORY
82	beq	btinfo_memory
83	add	r0, r0, r1
84	b	next_btinfo
85
86btinfo_memory_index:
87	.space	4
88
89btinfo_memory:
90	mov	r3, #0
91	str	r3, btinfo_memory_index
92
93	ldr	r3, [r0, #12]		/* Load size */
94	cmp	r3, #L1_S_SIZE
95	blt	map_l1c
96map_l1s:
97	/* Make L1 descriptor */
98	ldr	r3, [r0, #8]		/* Load phys address */
99	ldr	r2, btinfo_memory_index
100	add	r3, r2, r3
101	ldr	r2, startup_pagetable_l1s_attr
102	orr	r2, r2, r3
103
104	ldr	r1, startup_pagetable	/* pagetable */
105	ldr	r3, startup_space
106	add	r3, r3, #KERNEL_BASE
107	mov	r3, r3, lsr #(L1_S_SHIFT - 2)
108	add	r1, r3, r1
109	str	r2, [r1]
110
111	ldr	r2, btinfo_memory_index
112	add	r2, r2, #L1_S_SIZE
113	str	r2, btinfo_memory_index
114	ldr	r1, startup_space
115	add	r1, r1, #L1_S_SIZE
116	str	r1, startup_space
117	cmp	r1, #0x00400000		/* 4MB */
118	bge	99f
119	ldr	r1, [r0, #12]
120	cmp	r1, r2
121	bgt	map_l1s
122	ldr	r1, [r0]		/* Load size of btinfo_memory */
123	add	r0, r0, r1
124	b	next_btinfo
125
126map_l1c:
127	mov	r1, #1
128	mov	r2, r1, lsl #L1_S_SHIFT
129	sub	r2, r2, #1
130	ldr	r3, startup_space
131	ands	r2, r3, r2
132	bne	map_l2s
133
134	/* Make L1 descriptor */
135	ldr	r2, startup_pagetable
136	add	r2, r2, #L1_TABLE_SIZE	/* L2 table */
137	mov	r3, r3, lsr #(12 - 2)
138	add	r2, r2, r3
139	ldr	r3, startup_pagetable_l1c_attr
140	orr	r2, r2, r3
141
142	ldr	r1, startup_pagetable
143	ldr	r3, startup_space
144	add	r3, r3, #KERNEL_BASE
145	mov	r3, r3, lsr #(20 - 2)
146	add	r1, r1, r3
147	str	r2, [r1]
148
149map_l2s:
150	ldr	r1, [r0, #8]		/* Load phys address */
151	ldr	r2, btinfo_memory_index
152	add	r1, r1, r2
153	ldr	r2, startup_pagetable_l2s_attr
154	orr	r2, r1, r2
155
156	ldr	r1, startup_space
157	mov	r1, r1, lsr #(L2_S_SHIFT - 2)
158	ldr	r3, startup_pagetable
159	add	r3, r3, #L1_TABLE_SIZE	/* L2 table */
160	add	r1, r3, r1
161	str	r2, [r1]
162
163	ldr	r2, btinfo_memory_index
164	add	r2, r2, #L2_S_SIZE
165	str	r2, btinfo_memory_index
166	ldr	r1, startup_space
167	add	r1, r1, #L2_S_SIZE
168	str	r1, startup_space
169	cmp	r1, #0x00400000		/* 4MB */
170	bge	99f
171	ldr	r1, [r0, #12]
172	cmp	r1, r2
173	bgt	map_l2s
174	ldr	r1, [r0]		/* Load size of btinfo_memory */
175	add	r0, r0, r1
176	b	next_btinfo
177
17899:
179
180	/*
181	 * Set the Domain Access register.  Very important!
182	 * startup_pagetable puts to domain 0 now.
183	 */
184#define KERNEL_DOMAIN(x)	((x) << (PMAP_DOMAIN_KERNEL << 1))
185	mov	r0, #(KERNEL_DOMAIN(DOMAIN_CLIENT) | DOMAIN_CLIENT)
186	mcr	p15, 0, r0, c3, c0, 0
187
188	/*
189	 * Enable MMU and etc...
190	 */
191	ldr	r0, startup_pagetable
192	mcr	p15, 0, r0, c2, c0, 0	/* Set TTB */
193
194	mcr	p15, 0, r1, c0, c0, 0	/* Get ProcID */
195	and	r2, r1, #CPU_ID_IMPLEMENTOR_MASK
196	cmp	r2, #CPU_ID_DEC
197	beq	cpu_id_dec
198	ands	r2, r1, #CPU_ID_7ARCH_MASK
199	bne	cpu_id_7arch_v4t
200cpu_id_7arch_v3:	/* 7 */
201	mcr	p15, 0, r0, c5, c0, 0	/* Flash TLB */
202	b	enable_mmu
203
204cpu_id_7arch_v4t:	/* 7TDMI */
205cpu_id_dec:		/* SA1100 */
206	mov	r0, #0
207	mcr	p15, 0, r0, c8, c7, 0	/* Flash TLB */
208	nop
209
210enable_mmu:
211	ldr	r0, startup_control
212	mcr	p15, 0, r0, c1, c0, 0
213	nop
214	nop
215
216	/* Jump to kernel code in TRUE VA */
217	adr	r0, Lstart
218	ldr	pc, [r0]
219
220Lstart:
221	.word	start
222
223	.globl	_C_LABEL(startup_pagetable)
224startup_pagetable:
225#define STARTUP_PAGETABLE_ADDR		0xc0000000	/* aligned 16kByte */
226	.word	STARTUP_PAGETABLE_ADDR
227startup_pagetable_l1s_attr:
228	.word	L1_S_PROTO_generic | L1_S_C | L1_S_AP_KRW
229startup_pagetable_l1c_attr:
230	.word	L1_C_PROTO_generic
231startup_pagetable_l2s_attr:
232	.word	L2_S_PROTO_generic | L2_C | L2_AP_KRW
233startup_space:
234	.word	0x00000000
235startup_control:
236	.word	CPU_CONTROL_MMU_ENABLE  | \
237		CPU_CONTROL_DC_ENABLE   | \
238		CPU_CONTROL_WBUF_ENABLE | \
239		CPU_CONTROL_32BP_ENABLE | \
240		CPU_CONTROL_32BD_ENABLE | \
241		CPU_CONTROL_IC_ENABLE
242
243	.globl	_C_LABEL(bootinfo)
244bootinfo:
245	.space	BTINFO_MAX_SIZE
246
247#define MMU_INIT(va, pa, n_sec, attr)	  \
248	.word	n_sec			; \
249	.word	(va) >> (L1_S_SHIFT - 2); \
250	.word	(pa) | (attr)		;
251
252mmu_init_table:
253	/* fill all table VA==PA */
254	MMU_INIT(0x00000000, 0x00000000,
255	    1 << (32 - L1_S_SHIFT), L1_S_PROTO | L1_S_AP_KRW)
256	MMU_INIT(0, 0, 0, 0)		/* end of table */
257