xref: /openbmc/linux/arch/microblaze/kernel/head.S (revision cdd38c5f1ce4398ec58fec95904b75824daab7b5)
16d5af1a3SMichal Simek/*
26d5af1a3SMichal Simek * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
36d5af1a3SMichal Simek * Copyright (C) 2007-2009 PetaLogix
46d5af1a3SMichal Simek * Copyright (C) 2006 Atmark Techno, Inc.
56d5af1a3SMichal Simek *
65846cc60SMichal Simek * MMU code derived from arch/ppc/kernel/head_4xx.S:
75846cc60SMichal Simek *    Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org>
85846cc60SMichal Simek *      Initial PowerPC version.
95846cc60SMichal Simek *    Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu>
105846cc60SMichal Simek *      Rewritten for PReP
115846cc60SMichal Simek *    Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
125846cc60SMichal Simek *      Low-level exception handers, MMU support, and rewrite.
135846cc60SMichal Simek *    Copyright (c) 1997 Dan Malek <dmalek@jlc.net>
145846cc60SMichal Simek *      PowerPC 8xx modifications.
155846cc60SMichal Simek *    Copyright (c) 1998-1999 TiVo, Inc.
165846cc60SMichal Simek *      PowerPC 403GCX modifications.
175846cc60SMichal Simek *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
185846cc60SMichal Simek *      PowerPC 403GCX/405GP modifications.
195846cc60SMichal Simek *    Copyright 2000 MontaVista Software Inc.
205846cc60SMichal Simek *	PPC405 modifications
215846cc60SMichal Simek *      PowerPC 403GCX/405GP modifications.
225846cc60SMichal Simek * 	Author: MontaVista Software, Inc.
235846cc60SMichal Simek *         	frank_rowand@mvista.com or source@mvista.com
245846cc60SMichal Simek * 	   	debbie_chu@mvista.com
255846cc60SMichal Simek *
266d5af1a3SMichal Simek * This file is subject to the terms and conditions of the GNU General Public
276d5af1a3SMichal Simek * License. See the file "COPYING" in the main directory of this archive
286d5af1a3SMichal Simek * for more details.
296d5af1a3SMichal Simek */
306d5af1a3SMichal Simek
317a0248e8SSteven J. Magnani#include <linux/init.h>
326d5af1a3SMichal Simek#include <linux/linkage.h>
336d5af1a3SMichal Simek#include <asm/thread_info.h>
346d5af1a3SMichal Simek#include <asm/page.h>
35d8678b58SGrant Likely#include <linux/of_fdt.h>		/* for OF_DT_HEADER */
366d5af1a3SMichal Simek
375846cc60SMichal Simek#include <asm/setup.h> /* COMMAND_LINE_SIZE */
385846cc60SMichal Simek#include <asm/mmu.h>
395846cc60SMichal Simek#include <asm/processor.h>
405846cc60SMichal Simek
41495162dfSMichal Simek.section .data
425846cc60SMichal Simek.global empty_zero_page
435846cc60SMichal Simek.align 12
445846cc60SMichal Simekempty_zero_page:
45ba9c4f88SSteven J. Magnani	.space	PAGE_SIZE
465846cc60SMichal Simek.global swapper_pg_dir
475846cc60SMichal Simekswapper_pg_dir:
48ba9c4f88SSteven J. Magnani	.space	PAGE_SIZE
495846cc60SMichal Simek
50495162dfSMichal Simek.section .rodata
51495162dfSMichal Simek.align 4
52495162dfSMichal Simekendian_check:
53495162dfSMichal Simek	.word	1
54495162dfSMichal Simek
557a0248e8SSteven J. Magnani	__HEAD
566d5af1a3SMichal SimekENTRY(_start)
57ee68f174SMichal Simek#if CONFIG_KERNEL_BASE_ADDR == 0
58ee68f174SMichal Simek	brai	TOPHYS(real_start)
59ee68f174SMichal Simek	.org	0x100
60ee68f174SMichal Simekreal_start:
61ee68f174SMichal Simek#endif
62ee68f174SMichal Simek
63173701d7SMichal Simek	mts	rmsr, r0
6434b9c07aSMichal Simek/* Disable stack protection from bootloader */
6534b9c07aSMichal Simek	mts	rslr, r0
66a49f56eeSEdgar E. Iglesias	addi	r8, r0, 0xFFFFFFFF
6734b9c07aSMichal Simek	mts	rshr, r8
682622434eSMichal Simek/*
690eb6aaf5SMichal Simek * According to Xilinx, msrclr instruction behaves like 'mfs rX,rpc'
700eb6aaf5SMichal Simek * if the msrclr instruction is not enabled. We use this to detect
710eb6aaf5SMichal Simek * if the opcode is available, by issuing msrclr and then testing the result.
720eb6aaf5SMichal Simek * r8 == 0 - msr instructions are implemented
730eb6aaf5SMichal Simek * r8 != 0 - msr instructions are not implemented
742622434eSMichal Simek */
75173701d7SMichal Simek	mfs	r1, rmsr
760eb6aaf5SMichal Simek	msrclr	r8, 0 /* clear nothing - just read msr for test */
770eb6aaf5SMichal Simek	cmpu	r8, r8, r1 /* r1 must contain msr reg content */
782622434eSMichal Simek
79909964ecSJohn Williams/* r7 may point to an FDT, or there may be one linked in.
80909964ecSJohn Williams   if it's in r7, we've got to save it away ASAP.
81909964ecSJohn Williams   We ensure r7 points to a valid FDT, just in case the bootloader
82909964ecSJohn Williams   is broken or non-existent */
83909964ecSJohn Williams	beqi	r7, no_fdt_arg			/* NULL pointer?  don't copy */
84026a2078SMichal Simek/* Does r7 point to a valid FDT? Load HEADER magic number */
85026a2078SMichal Simek	/* Run time Big/Little endian platform */
86026a2078SMichal Simek	/* Save 1 as word and load byte - 0 - BIG, 1 - LITTLE */
87495162dfSMichal Simek	lbui	r11, r0, TOPHYS(endian_check)
88026a2078SMichal Simek	beqid	r11, big_endian /* DO NOT break delay stop dependency */
89026a2078SMichal Simek	lw	r11, r0, r7 /* Big endian load in delay slot */
90026a2078SMichal Simek	lwr	r11, r0, r7 /* Little endian load */
91026a2078SMichal Simekbig_endian:
92026a2078SMichal Simek	rsubi	r11, r11, OF_DT_HEADER	/* Check FDT header */
93ea3fd146SMichal Simek	beqi	r11, _prepare_copy_fdt
94ea3fd146SMichal Simek	or	r7, r0, r0		/* clear R7 when not valid DTB */
95909964ecSJohn Williams	bnei	r11, no_fdt_arg			/* No - get out of here */
96ea3fd146SMichal Simek_prepare_copy_fdt:
976d5af1a3SMichal Simek	or	r11, r0, r0 /* incremment */
98909964ecSJohn Williams	ori	r4, r0, TOPHYS(_fdt_start)
9922648c98SSiva Durga Prasad Paladugu	ori	r3, r0, (0x10000 - 4)
1006d5af1a3SMichal Simek_copy_fdt:
1016d5af1a3SMichal Simek	lw	r12, r7, r11 /* r12 = r7 + r11 */
1026d5af1a3SMichal Simek	sw	r12, r4, r11 /* addr[r4 + r11] = r12 */
1036d5af1a3SMichal Simek	addik	r11, r11, 4 /* increment counting */
1046d5af1a3SMichal Simek	bgtid	r3, _copy_fdt /* loop for all entries */
1056d5af1a3SMichal Simek	addik	r3, r3, -4 /* descrement loop */
1066d5af1a3SMichal Simekno_fdt_arg:
1076d5af1a3SMichal Simek
1085846cc60SMichal Simek#ifndef CONFIG_CMDLINE_BOOL
1095846cc60SMichal Simek/*
1105846cc60SMichal Simek * handling command line
111fcc1c0ffSMichal Simek * copy command line directly to cmd_line placed in data section.
1125846cc60SMichal Simek */
113fcc1c0ffSMichal Simek	beqid	r5, skip	/* Skip if NULL pointer */
1144323cd48SMichal Simek	or	r11, r0, r0		/* incremment */
115fcc1c0ffSMichal Simek	ori	r4, r0, cmd_line	/* load address of command line */
1165846cc60SMichal Simek	tophys(r4,r4)			/* convert to phys address */
1175846cc60SMichal Simek	ori	r3, r0, COMMAND_LINE_SIZE - 1 /* number of loops */
1185846cc60SMichal Simek_copy_command_line:
119*62fa3bc5SMichal Simek	/* r2=r5+r11 - r5 contain pointer to command line */
1204323cd48SMichal Simek	lbu	r2, r5, r11
121fcc1c0ffSMichal Simek	beqid	r2, skip		/* Skip if no data */
122*62fa3bc5SMichal Simek	sb	r2, r4, r11		/* addr[r4+r11]= r2 */
1234323cd48SMichal Simek	addik	r11, r11, 1		/* increment counting */
1245846cc60SMichal Simek	bgtid	r3, _copy_command_line	/* loop for all entries       */
125fcc1c0ffSMichal Simek	addik	r3, r3, -1		/* decrement loop */
1265846cc60SMichal Simek	addik	r5, r4, 0		/* add new space for command line */
1275846cc60SMichal Simek	tovirt(r5,r5)
128fcc1c0ffSMichal Simekskip:
1295846cc60SMichal Simek#endif /* CONFIG_CMDLINE_BOOL */
1305846cc60SMichal Simek
1315846cc60SMichal Simek#ifdef NOT_COMPILE
1325846cc60SMichal Simek/* save bram context */
1334323cd48SMichal Simek	or	r11, r0, r0				/* incremment */
1345846cc60SMichal Simek	ori	r4, r0, TOPHYS(_bram_load_start)	/* save bram context */
1355846cc60SMichal Simek	ori	r3, r0, (LMB_SIZE - 4)
1365846cc60SMichal Simek_copy_bram:
137*62fa3bc5SMichal Simek	lw	r7, r0, r11		/* r7 = r0 + r11 */
138*62fa3bc5SMichal Simek	sw	r7, r4, r11		/* addr[r4 + r11] = r7 */
1394323cd48SMichal Simek	addik	r11, r11, 4		/* increment counting */
1405846cc60SMichal Simek	bgtid	r3, _copy_bram		/* loop for all entries */
1415846cc60SMichal Simek	addik	r3, r3, -4		/* descrement loop */
1425846cc60SMichal Simek#endif
1435846cc60SMichal Simek	/* We have to turn on the MMU right away. */
1445846cc60SMichal Simek
1455846cc60SMichal Simek	/*
1465846cc60SMichal Simek	 * Set up the initial MMU state so we can do the first level of
1475846cc60SMichal Simek	 * kernel initialization.  This maps the first 16 MBytes of memory 1:1
1485846cc60SMichal Simek	 * virtual to physical.
1495846cc60SMichal Simek	 */
1505846cc60SMichal Simek	nop
1510691c97dSMichal Simek	addik	r3, r0, MICROBLAZE_TLB_SIZE -1	/* Invalidate all TLB entries */
1525846cc60SMichal Simek_invalidate:
1535846cc60SMichal Simek	mts	rtlbx, r3
1545846cc60SMichal Simek	mts	rtlbhi, r0			/* flush: ensure V is clear   */
155e02db0aaSMichal Simek	mts	rtlblo, r0
1565846cc60SMichal Simek	bgtid	r3, _invalidate		/* loop for all entries       */
1575846cc60SMichal Simek	addik	r3, r3, -1
1585846cc60SMichal Simek	/* sync */
1595846cc60SMichal Simek
160137d0795SMichal Simek	/* Setup the kernel PID */
161137d0795SMichal Simek	mts	rpid,r0			/* Load the kernel PID */
162137d0795SMichal Simek	nop
163137d0795SMichal Simek	bri	4
164137d0795SMichal Simek
1655846cc60SMichal Simek	/*
1665846cc60SMichal Simek	 * We should still be executing code at physical address area
1675846cc60SMichal Simek	 * RAM_BASEADDR at this point. However, kernel code is at
1685846cc60SMichal Simek	 * a virtual address. So, set up a TLB mapping to cover this once
1695846cc60SMichal Simek	 * translation is enabled.
1705846cc60SMichal Simek	 */
1715846cc60SMichal Simek
1725846cc60SMichal Simek	addik	r3,r0, CONFIG_KERNEL_START /* Load the kernel virtual address */
1735846cc60SMichal Simek	tophys(r4,r3)			/* Load the kernel physical address */
1745846cc60SMichal Simek
17595b0f9eaSMichal Simek	/* start to do TLB calculation */
17695b0f9eaSMichal Simek	addik	r12, r0, _end
17795b0f9eaSMichal Simek	rsub	r12, r3, r12
1787f15a256SMichal Simek	addik	r12, r12, CONFIG_LOWMEM_SIZE >> PTE_SHIFT /* that's the pad */
17995b0f9eaSMichal Simek
18095b0f9eaSMichal Simek	or r9, r0, r0 /* TLB0 = 0 */
18195b0f9eaSMichal Simek	or r10, r0, r0 /* TLB1 = 0 */
18295b0f9eaSMichal Simek
18395b0f9eaSMichal Simek	addik	r11, r12, -0x1000000
18495b0f9eaSMichal Simek	bgei	r11, GT16 /* size is greater than 16MB */
18595b0f9eaSMichal Simek	addik	r11, r12, -0x0800000
18695b0f9eaSMichal Simek	bgei	r11, GT8 /* size is greater than 8MB */
18795b0f9eaSMichal Simek	addik	r11, r12, -0x0400000
18895b0f9eaSMichal Simek	bgei	r11, GT4 /* size is greater than 4MB */
18995b0f9eaSMichal Simek	/* size is less than 4MB */
19095b0f9eaSMichal Simek	addik	r11, r12, -0x0200000
19195b0f9eaSMichal Simek	bgei	r11, GT2 /* size is greater than 2MB */
19295b0f9eaSMichal Simek	addik	r9, r0, 0x0100000 /* TLB0 must be 1MB */
19395b0f9eaSMichal Simek	addik	r11, r12, -0x0100000
19495b0f9eaSMichal Simek	bgei	r11, GT1 /* size is greater than 1MB */
19595b0f9eaSMichal Simek	/* TLB1 is 0 which is setup above */
19695b0f9eaSMichal Simek	bri tlb_end
19795b0f9eaSMichal SimekGT4: /* r11 contains the rest - will be either 1 or 4 */
19895b0f9eaSMichal Simek	ori r9, r0, 0x400000 /* TLB0 is 4MB */
19995b0f9eaSMichal Simek	bri TLB1
20095b0f9eaSMichal SimekGT16: /* TLB0 is 16MB */
20195b0f9eaSMichal Simek	addik	r9, r0, 0x1000000 /* means TLB0 is 16MB */
20295b0f9eaSMichal SimekTLB1:
203225fba21SAntonio Ospite	/* must be used r2 because of subtract if failed */
20495b0f9eaSMichal Simek	addik	r2, r11, -0x0400000
20595b0f9eaSMichal Simek	bgei	r2, GT20 /* size is greater than 16MB */
20695b0f9eaSMichal Simek	/* size is >16MB and <20MB */
20795b0f9eaSMichal Simek	addik	r11, r11, -0x0100000
20895b0f9eaSMichal Simek	bgei	r11, GT17 /* size is greater than 17MB */
20995b0f9eaSMichal Simek	/* kernel is >16MB and < 17MB */
21095b0f9eaSMichal SimekGT1:
21195b0f9eaSMichal Simek	addik	r10, r0, 0x0100000 /* means TLB1 is 1MB */
21295b0f9eaSMichal Simek	bri tlb_end
21395b0f9eaSMichal SimekGT2: /* TLB0 is 0 and TLB1 will be 4MB */
21495b0f9eaSMichal SimekGT17: /* TLB1 is 4MB - kernel size <20MB */
21595b0f9eaSMichal Simek	addik	r10, r0, 0x0400000 /* means TLB1 is 4MB */
21695b0f9eaSMichal Simek	bri tlb_end
21795b0f9eaSMichal SimekGT8: /* TLB0 is still zero that's why I can use only TLB1 */
21895b0f9eaSMichal SimekGT20: /* TLB1 is 16MB - kernel size >20MB */
21995b0f9eaSMichal Simek	addik	r10, r0, 0x1000000 /* means TLB1 is 16MB */
22095b0f9eaSMichal Simektlb_end:
22195b0f9eaSMichal Simek
2225846cc60SMichal Simek	/*
2235846cc60SMichal Simek	 * Configure and load two entries into TLB slots 0 and 1.
2245846cc60SMichal Simek	 * In case we are pinning TLBs, these are reserved in by the
2255846cc60SMichal Simek	 * other TLB functions.  If not reserving, then it doesn't
2265846cc60SMichal Simek	 * matter where they are loaded.
2275846cc60SMichal Simek	 */
2285846cc60SMichal Simek	andi	r4,r4,0xfffffc00	/* Mask off the real page number */
2295846cc60SMichal Simek	ori	r4,r4,(TLB_WR | TLB_EX)	/* Set the write and execute bits */
2305846cc60SMichal Simek
231e02db0aaSMichal Simek	/*
232e02db0aaSMichal Simek	 * TLB0 is always used - check if is not zero (r9 stores TLB0 value)
233e02db0aaSMichal Simek	 * if is use TLB1 value and clear it (r10 stores TLB1 value)
234e02db0aaSMichal Simek	 */
235e02db0aaSMichal Simek	bnei	r9, tlb0_not_zero
236e02db0aaSMichal Simek	add	r9, r10, r0
237e02db0aaSMichal Simek	add	r10, r0, r0
238e02db0aaSMichal Simektlb0_not_zero:
23995b0f9eaSMichal Simek
24095b0f9eaSMichal Simek	/* look at the code below */
24195b0f9eaSMichal Simek	ori	r30, r0, 0x200
24295b0f9eaSMichal Simek	andi	r29, r9, 0x100000
24395b0f9eaSMichal Simek	bneid	r29, 1f
24495b0f9eaSMichal Simek	addik	r30, r30, 0x80
24595b0f9eaSMichal Simek	andi	r29, r9, 0x400000
24695b0f9eaSMichal Simek	bneid	r29, 1f
24795b0f9eaSMichal Simek	addik	r30, r30, 0x80
24895b0f9eaSMichal Simek	andi	r29, r9, 0x1000000
24995b0f9eaSMichal Simek	bneid	r29, 1f
25095b0f9eaSMichal Simek	addik	r30, r30, 0x80
25195b0f9eaSMichal Simek1:
2525846cc60SMichal Simek	andi	r3,r3,0xfffffc00	/* Mask off the effective page number */
25395b0f9eaSMichal Simek	ori	r3,r3,(TLB_VALID)
254e02db0aaSMichal Simek	or	r3, r3, r30
2555846cc60SMichal Simek
256e02db0aaSMichal Simek	/* Load tlb_skip size value which is index to first unused TLB entry */
257e02db0aaSMichal Simek	lwi	r11, r0, TOPHYS(tlb_skip)
258e02db0aaSMichal Simek	mts     rtlbx,r11		/* TLB slow 0 */
2595846cc60SMichal Simek
2605846cc60SMichal Simek	mts	rtlblo,r4		/* Load the data portion of the entry */
2615846cc60SMichal Simek	mts	rtlbhi,r3		/* Load the tag portion of the entry */
2625846cc60SMichal Simek
263e02db0aaSMichal Simek	/* Increase tlb_skip size */
264e02db0aaSMichal Simek	addik	r11, r11, 1
265e02db0aaSMichal Simek	swi	r11, r0, TOPHYS(tlb_skip)
266e02db0aaSMichal Simek
26795b0f9eaSMichal Simek	/* TLB1 can be zeroes that's why we not setup it */
26895b0f9eaSMichal Simek	beqi	r10, jump_over2
26995b0f9eaSMichal Simek
27095b0f9eaSMichal Simek	/* look at the code below */
27195b0f9eaSMichal Simek	ori	r30, r0, 0x200
27295b0f9eaSMichal Simek	andi	r29, r10, 0x100000
27395b0f9eaSMichal Simek	bneid	r29, 1f
27495b0f9eaSMichal Simek	addik	r30, r30, 0x80
27595b0f9eaSMichal Simek	andi	r29, r10, 0x400000
27695b0f9eaSMichal Simek	bneid	r29, 1f
27795b0f9eaSMichal Simek	addik	r30, r30, 0x80
27895b0f9eaSMichal Simek	andi	r29, r10, 0x1000000
27995b0f9eaSMichal Simek	bneid	r29, 1f
28095b0f9eaSMichal Simek	addik	r30, r30, 0x80
28195b0f9eaSMichal Simek1:
28295b0f9eaSMichal Simek	addk	r4, r4, r9	/* previous addr + TLB0 size */
28395b0f9eaSMichal Simek	addk	r3, r3, r9
28495b0f9eaSMichal Simek
28595b0f9eaSMichal Simek	andi	r3,r3,0xfffffc00	/* Mask off the effective page number */
28695b0f9eaSMichal Simek	ori	r3,r3,(TLB_VALID)
287e02db0aaSMichal Simek	or	r3, r3, r30
2885846cc60SMichal Simek
289e02db0aaSMichal Simek	lwi	r11, r0, TOPHYS(tlb_skip)
290e02db0aaSMichal Simek	mts     rtlbx, r11		/* r11 is used from TLB0 */
2915846cc60SMichal Simek
2925846cc60SMichal Simek	mts	rtlblo,r4		/* Load the data portion of the entry */
2935846cc60SMichal Simek	mts	rtlbhi,r3		/* Load the tag portion of the entry */
2945846cc60SMichal Simek
295e02db0aaSMichal Simek	/* Increase tlb_skip size */
296e02db0aaSMichal Simek	addik	r11, r11, 1
297e02db0aaSMichal Simek	swi	r11, r0, TOPHYS(tlb_skip)
298e02db0aaSMichal Simek
29995b0f9eaSMichal Simekjump_over2:
3005846cc60SMichal Simek	/*
3015846cc60SMichal Simek	 * Load a TLB entry for LMB, since we need access to
3025846cc60SMichal Simek	 * the exception vectors, using a 4k real==virtual mapping.
3035846cc60SMichal Simek	 */
304e02db0aaSMichal Simek	/* Use temporary TLB_ID for LMB - clear this temporary mapping later */
3054323cd48SMichal Simek	ori	r11, r0, MICROBLAZE_LMB_TLB_ID
3064323cd48SMichal Simek	mts     rtlbx,r11
3075846cc60SMichal Simek
3085846cc60SMichal Simek	ori	r4,r0,(TLB_WR | TLB_EX)
3095846cc60SMichal Simek	ori	r3,r0,(TLB_VALID | TLB_PAGESZ(PAGESZ_4K))
3105846cc60SMichal Simek
3115846cc60SMichal Simek	mts	rtlblo,r4		/* Load the data portion of the entry */
3125846cc60SMichal Simek	mts	rtlbhi,r3		/* Load the tag portion of the entry */
3135846cc60SMichal Simek
3145846cc60SMichal Simek	/*
3155846cc60SMichal Simek	 * We now have the lower 16 Meg of RAM mapped into TLB entries, and the
3165846cc60SMichal Simek	 * caches ready to work.
3175846cc60SMichal Simek	 */
3185846cc60SMichal Simekturn_on_mmu:
3195846cc60SMichal Simek	ori	r15,r0,start_here
3205846cc60SMichal Simek	ori	r4,r0,MSR_KERNEL_VMS
3215846cc60SMichal Simek	mts	rmsr,r4
3225846cc60SMichal Simek	nop
3235846cc60SMichal Simek	rted	r15,0			/* enables MMU */
3245846cc60SMichal Simek	nop
3255846cc60SMichal Simek
3265846cc60SMichal Simekstart_here:
3275846cc60SMichal Simek
3286d5af1a3SMichal Simek	/* Initialize small data anchors */
329cd341577SMichal Simek	addik	r13, r0, _KERNEL_SDA_BASE_
330cd341577SMichal Simek	addik	r2, r0, _KERNEL_SDA2_BASE_
3316d5af1a3SMichal Simek
3326d5af1a3SMichal Simek	/* Initialize stack pointer */
333cd341577SMichal Simek	addik	r1, r0, init_thread_union + THREAD_SIZE - 4
3346d5af1a3SMichal Simek
3356d5af1a3SMichal Simek	/* Initialize r31 with current task address */
336cd341577SMichal Simek	addik	r31, r0, init_task
3376d5af1a3SMichal Simek
33895b0f9eaSMichal Simek	addik	r11, r0, machine_early_init
33995b0f9eaSMichal Simek	brald	r15, r11
3406d5af1a3SMichal Simek	nop
3416d5af1a3SMichal Simek
3425846cc60SMichal Simek	/*
3435846cc60SMichal Simek	 * Initialize the MMU.
3445846cc60SMichal Simek	 */
3455846cc60SMichal Simek	bralid	r15, mmu_init
3465846cc60SMichal Simek	nop
3475846cc60SMichal Simek
3485846cc60SMichal Simek	/* Go back to running unmapped so we can load up new values
3495846cc60SMichal Simek	 * and change to using our exception vectors.
3505846cc60SMichal Simek	 * On the MicroBlaze, all we invalidate the used TLB entries to clear
3515846cc60SMichal Simek	 * the old 16M byte TLB mappings.
3525846cc60SMichal Simek	 */
3535846cc60SMichal Simek	ori	r15,r0,TOPHYS(kernel_load_context)
3545846cc60SMichal Simek	ori	r4,r0,MSR_KERNEL
3555846cc60SMichal Simek	mts	rmsr,r4
3565846cc60SMichal Simek	nop
3575846cc60SMichal Simek	bri	4
3585846cc60SMichal Simek	rted	r15,0
3595846cc60SMichal Simek	nop
3605846cc60SMichal Simek
3615846cc60SMichal Simek	/* Load up the kernel context */
3625846cc60SMichal Simekkernel_load_context:
363e02db0aaSMichal Simek	ori	r5, r0, MICROBLAZE_LMB_TLB_ID
3645846cc60SMichal Simek	mts     rtlbx,r5
3655846cc60SMichal Simek	nop
3665846cc60SMichal Simek	mts	rtlbhi,r0
3675846cc60SMichal Simek	nop
3685846cc60SMichal Simek	addi	r15, r0, machine_halt
3695846cc60SMichal Simek	ori	r17, r0, start_kernel
3705846cc60SMichal Simek	ori	r4, r0, MSR_KERNEL_VMS
3715846cc60SMichal Simek	mts	rmsr, r4
3725846cc60SMichal Simek	nop
3735846cc60SMichal Simek	rted	r17, 0		/* enable MMU and jump to start_kernel */
3745846cc60SMichal Simek	nop
375